aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile6
-rw-r--r--tools/build/Makefile.build8
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/gpio/lsgpio.c2
-rw-r--r--tools/hv/lsvmbus1
-rw-r--r--tools/iio/generic_buffer.c116
-rw-r--r--tools/iio/iio_event_monitor.c18
-rw-r--r--tools/iio/iio_utils.h7
-rw-r--r--tools/kvm/kvm_stat/Makefile41
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat1127
-rw-r--r--tools/kvm/kvm_stat/kvm_stat.txt63
-rw-r--r--tools/objtool/Makefile4
-rw-r--r--tools/objtool/elf.h5
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h69
-rw-r--r--tools/perf/arch/powerpc/util/Build2
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c49
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libunwind.c96
-rw-r--r--tools/perf/config/Makefile6
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c2
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/machine.c2
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/perf_regs.c8
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c47
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c24
-rw-r--r--tools/power/acpi/tools/acpidbg/acpidbg.c4
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile1
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c13
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c3
-rw-r--r--tools/power/cpupower/Makefile12
-rw-r--r--tools/power/cpupower/bench/Makefile2
-rw-r--r--tools/power/cpupower/bench/README-BENCH2
-rw-r--r--tools/power/cpupower/bench/benchmark.c4
-rw-r--r--tools/power/cpupower/bench/parse.c20
-rw-r--r--tools/power/cpupower/bench/system.c3
-rw-r--r--tools/power/cpupower/lib/cpufreq.c550
-rw-r--r--tools/power/cpupower/lib/cpufreq.h59
-rw-r--r--tools/power/cpupower/lib/cpuidle.c380
-rw-r--r--tools/power/cpupower/lib/cpuidle.h23
-rw-r--r--tools/power/cpupower/lib/cpupower.c192
-rw-r--r--tools/power/cpupower/lib/cpupower.h35
-rw-r--r--tools/power/cpupower/lib/cpupower_intern.h5
-rw-r--r--tools/power/cpupower/lib/sysfs.c672
-rw-r--r--tools/power/cpupower/lib/sysfs.h31
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-info.12
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-set.12
-rw-r--r--tools/power/cpupower/man/cpupower-idle-info.12
-rw-r--r--tools/power/cpupower/man/cpupower-idle-set.12
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c8
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c32
-rw-r--r--tools/power/cpupower/utils/cpuidle-set.c26
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h26
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c107
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c12
-rw-r--r--tools/testing/nvdimm/Kbuild11
-rw-r--r--tools/testing/nvdimm/config_check.c2
-rw-r--r--tools/testing/nvdimm/test/iomap.c27
-rw-r--r--tools/testing/nvdimm/test/nfit.c90
-rw-r--r--tools/testing/radix-tree/Makefile4
-rw-r--r--tools/testing/radix-tree/generated/autoconf.h3
-rw-r--r--tools/testing/radix-tree/linux/init.h1
-rw-r--r--tools/testing/radix-tree/linux/kernel.h15
-rw-r--r--tools/testing/radix-tree/linux/slab.h1
-rw-r--r--tools/testing/radix-tree/linux/types.h7
-rw-r--r--tools/testing/radix-tree/main.c84
-rw-r--r--tools/testing/radix-tree/multiorder.c337
-rw-r--r--tools/testing/radix-tree/regression2.c7
-rw-r--r--tools/testing/radix-tree/tag_check.c10
-rw-r--r--tools/testing/radix-tree/test.c49
-rw-r--r--tools/testing/radix-tree/test.h11
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest9
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-pid.tc72
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions9
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance-event.tc138
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc64
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc59
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc75
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc83
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc73
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc56
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc53
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc58
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh2
-rw-r--r--tools/testing/selftests/net/reuseport_bpf.c10
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/Makefile10
-rw-r--r--tools/testing/selftests/powerpc/context_switch/cp_abort.c110
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c18
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c1
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c1
-rw-r--r--tools/testing/selftests/powerpc/reg.h (renamed from tools/testing/selftests/powerpc/pmu/ebb/reg.h)18
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-fork.c42
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c16
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-stack.c4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tar.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tmspr.c143
-rw-r--r--tools/testing/selftests/powerpc/utils.h8
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c38
-rw-r--r--tools/testing/selftests/vm/thuge-gen.c2
-rw-r--r--tools/usb/usbip/libsrc/Makefile.am4
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h3
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.c163
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.h34
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c273
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.h104
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.c269
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.h27
-rw-r--r--tools/usb/usbip/src/usbip_attach.c10
-rw-r--r--tools/usb/usbip/src/usbip_list.c96
-rw-r--r--tools/usb/usbip/src/usbip_port.c13
-rw-r--r--tools/usb/usbip/src/usbipd.c42
-rw-r--r--tools/virtio/ringtest/Makefile5
-rw-r--r--tools/virtio/ringtest/main.c2
-rw-r--r--tools/virtio/ringtest/virtio_ring_0_9.c49
-rw-r--r--tools/virtio/ringtest/virtio_ring_inorder.c2
120 files changed, 5566 insertions, 1402 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 6bf68fe7dd29..f10b64d8c674 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -16,6 +16,7 @@ help:
16 @echo ' gpio - GPIO tools' 16 @echo ' gpio - GPIO tools'
17 @echo ' hv - tools used when in Hyper-V clients' 17 @echo ' hv - tools used when in Hyper-V clients'
18 @echo ' iio - IIO tools' 18 @echo ' iio - IIO tools'
19 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
19 @echo ' lguest - a minimal 32-bit x86 hypervisor' 20 @echo ' lguest - a minimal 32-bit x86 hypervisor'
20 @echo ' net - misc networking tools' 21 @echo ' net - misc networking tools'
21 @echo ' perf - Linux performance measurement and analysis tool' 22 @echo ' perf - Linux performance measurement and analysis tool'
@@ -110,10 +111,13 @@ tmon_install:
110freefall_install: 111freefall_install:
111 $(call descend,laptop/$(@:_install=),install) 112 $(call descend,laptop/$(@:_install=),install)
112 113
114kvm_stat_install:
115 $(call descend,kvm/$(@:_install=),install)
116
113install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ 117install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
114 perf_install selftests_install turbostat_install usb_install \ 118 perf_install selftests_install turbostat_install usb_install \
115 virtio_install vm_install net_install x86_energy_perf_policy_install \ 119 virtio_install vm_install net_install x86_energy_perf_policy_install \
116 tmon_install freefall_install objtool_install 120 tmon_install freefall_install objtool_install kvm_stat_install
117 121
118acpi_clean: 122acpi_clean:
119 $(call descend,power/acpi,clean) 123 $(call descend,power/acpi,clean)
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index ee566e8bd1cf..27f3583193e6 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -58,8 +58,8 @@ quiet_cmd_mkdir = MKDIR $(dir $@)
58quiet_cmd_cc_o_c = CC $@ 58quiet_cmd_cc_o_c = CC $@
59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< 59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
60 60
61quiet_cmd_cc_i_c = CPP $@ 61quiet_cmd_cpp_i_c = CPP $@
62 cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $< 62 cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $<
63 63
64quiet_cmd_cc_s_c = AS $@ 64quiet_cmd_cc_s_c = AS $@
65 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< 65 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
@@ -83,11 +83,11 @@ $(OUTPUT)%.o: %.S FORCE
83 83
84$(OUTPUT)%.i: %.c FORCE 84$(OUTPUT)%.i: %.c FORCE
85 $(call rule_mkdir) 85 $(call rule_mkdir)
86 $(call if_changed_dep,cc_i_c) 86 $(call if_changed_dep,cpp_i_c)
87 87
88$(OUTPUT)%.s: %.S FORCE 88$(OUTPUT)%.s: %.S FORCE
89 $(call rule_mkdir) 89 $(call rule_mkdir)
90 $(call if_changed_dep,cc_i_c) 90 $(call if_changed_dep,cpp_i_c)
91 91
92$(OUTPUT)%.s: %.c FORCE 92$(OUTPUT)%.s: %.c FORCE
93 $(call rule_mkdir) 93 $(call rule_mkdir)
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 4d198d5c4203..c155d6bc47a7 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -1,5 +1,5 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE 2CFLAGS += -O2 -Wall -g -D_GNU_SOURCE
3 3
4all: lsgpio 4all: lsgpio
5 5
diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c
index 1124da375942..eb3f56efd215 100644
--- a/tools/gpio/lsgpio.c
+++ b/tools/gpio/lsgpio.c
@@ -147,7 +147,7 @@ void print_usage(void)
147 147
148int main(int argc, char **argv) 148int main(int argc, char **argv)
149{ 149{
150 const char *device_name; 150 const char *device_name = NULL;
151 int ret; 151 int ret;
152 int c; 152 int c;
153 153
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
index 162a3784d80e..e8fecd61871f 100644
--- a/tools/hv/lsvmbus
+++ b/tools/hv/lsvmbus
@@ -35,6 +35,7 @@ vmbus_dev_dict = {
35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller', 35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter', 36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter', 37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
38 '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
38 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]', 39 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
39 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]', 40 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
40 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]', 41 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
index 01c4f67801e0..2429c78de940 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/generic_buffer.c
@@ -35,6 +35,15 @@
35#include "iio_utils.h" 35#include "iio_utils.h"
36 36
37/** 37/**
38 * enum autochan - state for the automatic channel enabling mechanism
39 */
40enum autochan {
41 AUTOCHANNELS_DISABLED,
42 AUTOCHANNELS_ENABLED,
43 AUTOCHANNELS_ACTIVE,
44};
45
46/**
38 * size_from_channelarray() - calculate the storage size of a scan 47 * size_from_channelarray() - calculate the storage size of a scan
39 * @channels: the channel info array 48 * @channels: the channel info array
40 * @num_channels: number of channels 49 * @num_channels: number of channels
@@ -191,10 +200,51 @@ void process_scan(char *data,
191 printf("\n"); 200 printf("\n");
192} 201}
193 202
203static int enable_disable_all_channels(char *dev_dir_name, int enable)
204{
205 const struct dirent *ent;
206 char scanelemdir[256];
207 DIR *dp;
208 int ret;
209
210 snprintf(scanelemdir, sizeof(scanelemdir),
211 FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
212 scanelemdir[sizeof(scanelemdir)-1] = '\0';
213
214 dp = opendir(scanelemdir);
215 if (!dp) {
216 fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
217 scanelemdir);
218 return -EIO;
219 }
220
221 ret = -ENOENT;
222 while (ent = readdir(dp), ent) {
223 if (iioutils_check_suffix(ent->d_name, "_en")) {
224 printf("%sabling: %s\n",
225 enable ? "En" : "Dis",
226 ent->d_name);
227 ret = write_sysfs_int(ent->d_name, scanelemdir,
228 enable);
229 if (ret < 0)
230 fprintf(stderr, "Failed to enable/disable %s\n",
231 ent->d_name);
232 }
233 }
234
235 if (closedir(dp) == -1) {
236 perror("Enabling/disabling channels: "
237 "Failed to close directory");
238 return -errno;
239 }
240 return 0;
241}
242
194void print_usage(void) 243void print_usage(void)
195{ 244{
196 fprintf(stderr, "Usage: generic_buffer [options]...\n" 245 fprintf(stderr, "Usage: generic_buffer [options]...\n"
197 "Capture, convert and output data from IIO device buffer\n" 246 "Capture, convert and output data from IIO device buffer\n"
247 " -a Auto-activate all available channels\n"
198 " -c <n> Do n conversions\n" 248 " -c <n> Do n conversions\n"
199 " -e Disable wait for event (new data)\n" 249 " -e Disable wait for event (new data)\n"
200 " -g Use trigger-less mode\n" 250 " -g Use trigger-less mode\n"
@@ -225,12 +275,16 @@ int main(int argc, char **argv)
225 int scan_size; 275 int scan_size;
226 int noevents = 0; 276 int noevents = 0;
227 int notrigger = 0; 277 int notrigger = 0;
278 enum autochan autochannels = AUTOCHANNELS_DISABLED;
228 char *dummy; 279 char *dummy;
229 280
230 struct iio_channel_info *channels; 281 struct iio_channel_info *channels;
231 282
232 while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) { 283 while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) {
233 switch (c) { 284 switch (c) {
285 case 'a':
286 autochannels = AUTOCHANNELS_ENABLED;
287 break;
234 case 'c': 288 case 'c':
235 errno = 0; 289 errno = 0;
236 num_loops = strtoul(optarg, &dummy, 10); 290 num_loops = strtoul(optarg, &dummy, 10);
@@ -304,7 +358,19 @@ int main(int argc, char **argv)
304 } 358 }
305 } 359 }
306 360
307 /* Verify the trigger exists */ 361 /* Look for this "-devN" trigger */
362 trig_num = find_type_by_name(trigger_name, "trigger");
363 if (trig_num < 0) {
364 /* OK try the simpler "-trigger" suffix instead */
365 free(trigger_name);
366 ret = asprintf(&trigger_name,
367 "%s-trigger", device_name);
368 if (ret < 0) {
369 ret = -ENOMEM;
370 goto error_free_dev_dir_name;
371 }
372 }
373
308 trig_num = find_type_by_name(trigger_name, "trigger"); 374 trig_num = find_type_by_name(trigger_name, "trigger");
309 if (trig_num < 0) { 375 if (trig_num < 0) {
310 fprintf(stderr, "Failed to find the trigger %s\n", 376 fprintf(stderr, "Failed to find the trigger %s\n",
@@ -328,12 +394,47 @@ int main(int argc, char **argv)
328 "diag %s\n", dev_dir_name); 394 "diag %s\n", dev_dir_name);
329 goto error_free_triggername; 395 goto error_free_triggername;
330 } 396 }
331 if (!num_channels) { 397 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) {
398 fprintf(stderr, "Auto-channels selected but some channels "
399 "are already activated in sysfs\n");
400 fprintf(stderr, "Proceeding without activating any channels\n");
401 }
402
403 if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) {
404 fprintf(stderr,
405 "No channels are enabled, enabling all channels\n");
406
407 ret = enable_disable_all_channels(dev_dir_name, 1);
408 if (ret) {
409 fprintf(stderr, "Failed to enable all channels\n");
410 goto error_free_triggername;
411 }
412
413 /* This flags that we need to disable the channels again */
414 autochannels = AUTOCHANNELS_ACTIVE;
415
416 ret = build_channel_array(dev_dir_name, &channels,
417 &num_channels);
418 if (ret) {
419 fprintf(stderr, "Problem reading scan element "
420 "information\n"
421 "diag %s\n", dev_dir_name);
422 goto error_disable_channels;
423 }
424 if (!num_channels) {
425 fprintf(stderr, "Still no channels after "
426 "auto-enabling, giving up\n");
427 goto error_disable_channels;
428 }
429 }
430
431 if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
332 fprintf(stderr, 432 fprintf(stderr,
333 "No channels are enabled, we have nothing to scan.\n"); 433 "No channels are enabled, we have nothing to scan.\n");
334 fprintf(stderr, "Enable channels manually in " 434 fprintf(stderr, "Enable channels manually in "
335 FORMAT_SCAN_ELEMENTS_DIR 435 FORMAT_SCAN_ELEMENTS_DIR
336 "/*_en and try again.\n", dev_dir_name); 436 "/*_en or pass -a to autoenable channels and "
437 "try again.\n", dev_dir_name);
337 ret = -ENOENT; 438 ret = -ENOENT;
338 goto error_free_triggername; 439 goto error_free_triggername;
339 } 440 }
@@ -467,7 +568,12 @@ error_free_channels:
467error_free_triggername: 568error_free_triggername:
468 if (datardytrigger) 569 if (datardytrigger)
469 free(trigger_name); 570 free(trigger_name);
470 571error_disable_channels:
572 if (autochannels == AUTOCHANNELS_ACTIVE) {
573 ret = enable_disable_all_channels(dev_dir_name, 0);
574 if (ret)
575 fprintf(stderr, "Failed to disable all channels\n");
576 }
471error_free_dev_dir_name: 577error_free_dev_dir_name:
472 free(dev_dir_name); 578 free(dev_dir_name);
473 579
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index d51eb04202e9..d9b7e0f306c6 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -53,6 +53,10 @@ static const char * const iio_chan_type_name_spec[] = {
53 [IIO_ENERGY] = "energy", 53 [IIO_ENERGY] = "energy",
54 [IIO_DISTANCE] = "distance", 54 [IIO_DISTANCE] = "distance",
55 [IIO_VELOCITY] = "velocity", 55 [IIO_VELOCITY] = "velocity",
56 [IIO_CONCENTRATION] = "concentration",
57 [IIO_RESISTANCE] = "resistance",
58 [IIO_PH] = "ph",
59 [IIO_UVINDEX] = "uvindex",
56}; 60};
57 61
58static const char * const iio_ev_type_text[] = { 62static const char * const iio_ev_type_text[] = {
@@ -90,6 +94,7 @@ static const char * const iio_modifier_names[] = {
90 [IIO_MOD_LIGHT_RED] = "red", 94 [IIO_MOD_LIGHT_RED] = "red",
91 [IIO_MOD_LIGHT_GREEN] = "green", 95 [IIO_MOD_LIGHT_GREEN] = "green",
92 [IIO_MOD_LIGHT_BLUE] = "blue", 96 [IIO_MOD_LIGHT_BLUE] = "blue",
97 [IIO_MOD_LIGHT_UV] = "uv",
93 [IIO_MOD_QUATERNION] = "quaternion", 98 [IIO_MOD_QUATERNION] = "quaternion",
94 [IIO_MOD_TEMP_AMBIENT] = "ambient", 99 [IIO_MOD_TEMP_AMBIENT] = "ambient",
95 [IIO_MOD_TEMP_OBJECT] = "object", 100 [IIO_MOD_TEMP_OBJECT] = "object",
@@ -102,6 +107,10 @@ static const char * const iio_modifier_names[] = {
102 [IIO_MOD_WALKING] = "walking", 107 [IIO_MOD_WALKING] = "walking",
103 [IIO_MOD_STILL] = "still", 108 [IIO_MOD_STILL] = "still",
104 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", 109 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
110 [IIO_MOD_I] = "i",
111 [IIO_MOD_Q] = "q",
112 [IIO_MOD_CO2] = "co2",
113 [IIO_MOD_VOC] = "voc",
105}; 114};
106 115
107static bool event_is_known(struct iio_event_data *event) 116static bool event_is_known(struct iio_event_data *event)
@@ -136,6 +145,10 @@ static bool event_is_known(struct iio_event_data *event)
136 case IIO_ENERGY: 145 case IIO_ENERGY:
137 case IIO_DISTANCE: 146 case IIO_DISTANCE:
138 case IIO_VELOCITY: 147 case IIO_VELOCITY:
148 case IIO_CONCENTRATION:
149 case IIO_RESISTANCE:
150 case IIO_PH:
151 case IIO_UVINDEX:
139 break; 152 break;
140 default: 153 default:
141 return false; 154 return false;
@@ -162,6 +175,7 @@ static bool event_is_known(struct iio_event_data *event)
162 case IIO_MOD_LIGHT_RED: 175 case IIO_MOD_LIGHT_RED:
163 case IIO_MOD_LIGHT_GREEN: 176 case IIO_MOD_LIGHT_GREEN:
164 case IIO_MOD_LIGHT_BLUE: 177 case IIO_MOD_LIGHT_BLUE:
178 case IIO_MOD_LIGHT_UV:
165 case IIO_MOD_QUATERNION: 179 case IIO_MOD_QUATERNION:
166 case IIO_MOD_TEMP_AMBIENT: 180 case IIO_MOD_TEMP_AMBIENT:
167 case IIO_MOD_TEMP_OBJECT: 181 case IIO_MOD_TEMP_OBJECT:
@@ -174,6 +188,10 @@ static bool event_is_known(struct iio_event_data *event)
174 case IIO_MOD_WALKING: 188 case IIO_MOD_WALKING:
175 case IIO_MOD_STILL: 189 case IIO_MOD_STILL:
176 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z: 190 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
191 case IIO_MOD_I:
192 case IIO_MOD_Q:
193 case IIO_MOD_CO2:
194 case IIO_MOD_VOC:
177 break; 195 break;
178 default: 196 default:
179 return false; 197 return false;
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index e3503bfe538b..780f2014f8fa 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -52,6 +52,13 @@ struct iio_channel_info {
52 unsigned location; 52 unsigned location;
53}; 53};
54 54
55static inline int iioutils_check_suffix(const char *str, const char *suffix)
56{
57 return strlen(str) >= strlen(suffix) &&
58 strncmp(str+strlen(str)-strlen(suffix),
59 suffix, strlen(suffix)) == 0;
60}
61
55int iioutils_break_up_name(const char *full_name, char **generic_name); 62int iioutils_break_up_name(const char *full_name, char **generic_name);
56int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, 63int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
57 unsigned *shift, uint64_t *mask, unsigned *be, 64 unsigned *shift, uint64_t *mask, unsigned *be,
diff --git a/tools/kvm/kvm_stat/Makefile b/tools/kvm/kvm_stat/Makefile
new file mode 100644
index 000000000000..5b1cba57e3b3
--- /dev/null
+++ b/tools/kvm/kvm_stat/Makefile
@@ -0,0 +1,41 @@
1include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak
3BINDIR=usr/bin
4MANDIR=usr/share/man
5MAN1DIR=$(MANDIR)/man1
6
7MAN1=kvm_stat.1
8
9A2X=a2x
10a2x_path := $(call get-executable,$(A2X))
11
12all: man
13
14ifneq ($(findstring $(MAKEFLAGS),s),s)
15 ifneq ($(V),1)
16 QUIET_A2X = @echo ' A2X '$@;
17 endif
18endif
19
20%.1: %.txt
21ifeq ($(a2x_path),)
22 $(error "You need to install asciidoc for man pages")
23else
24 $(QUIET_A2X)$(A2X) --doctype manpage --format manpage $<
25endif
26
27clean:
28 rm -f $(MAN1)
29
30man: $(MAN1)
31
32install-man: man
33 install -d -m 755 $(INSTALL_ROOT)/$(MAN1DIR)
34 install -m 644 kvm_stat.1 $(INSTALL_ROOT)/$(MAN1DIR)
35
36install-tools:
37 install -d -m 755 $(INSTALL_ROOT)/$(BINDIR)
38 install -m 755 -p "kvm_stat" "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)"
39
40install: install-tools install-man
41.PHONY: all clean man install-tools install-man install
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
new file mode 100755
index 000000000000..581278c58488
--- /dev/null
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -0,0 +1,1127 @@
1#!/usr/bin/python
2#
3# top-like utility for displaying kvm statistics
4#
5# Copyright 2006-2008 Qumranet Technologies
6# Copyright 2008-2011 Red Hat, Inc.
7#
8# Authors:
9# Avi Kivity <avi@redhat.com>
10#
11# This work is licensed under the terms of the GNU GPL, version 2. See
12# the COPYING file in the top-level directory.
13"""The kvm_stat module outputs statistics about running KVM VMs
14
15Three different ways of output formatting are available:
16- as a top-like text ui
17- in a key -> value format
18- in an all keys, all values format
19
20The data is sampled from the KVM's debugfs entries and its perf events.
21"""
22
23import curses
24import sys
25import os
26import time
27import optparse
28import ctypes
29import fcntl
30import resource
31import struct
32import re
33from collections import defaultdict
34from time import sleep
35
36VMX_EXIT_REASONS = {
37 'EXCEPTION_NMI': 0,
38 'EXTERNAL_INTERRUPT': 1,
39 'TRIPLE_FAULT': 2,
40 'PENDING_INTERRUPT': 7,
41 'NMI_WINDOW': 8,
42 'TASK_SWITCH': 9,
43 'CPUID': 10,
44 'HLT': 12,
45 'INVLPG': 14,
46 'RDPMC': 15,
47 'RDTSC': 16,
48 'VMCALL': 18,
49 'VMCLEAR': 19,
50 'VMLAUNCH': 20,
51 'VMPTRLD': 21,
52 'VMPTRST': 22,
53 'VMREAD': 23,
54 'VMRESUME': 24,
55 'VMWRITE': 25,
56 'VMOFF': 26,
57 'VMON': 27,
58 'CR_ACCESS': 28,
59 'DR_ACCESS': 29,
60 'IO_INSTRUCTION': 30,
61 'MSR_READ': 31,
62 'MSR_WRITE': 32,
63 'INVALID_STATE': 33,
64 'MWAIT_INSTRUCTION': 36,
65 'MONITOR_INSTRUCTION': 39,
66 'PAUSE_INSTRUCTION': 40,
67 'MCE_DURING_VMENTRY': 41,
68 'TPR_BELOW_THRESHOLD': 43,
69 'APIC_ACCESS': 44,
70 'EPT_VIOLATION': 48,
71 'EPT_MISCONFIG': 49,
72 'WBINVD': 54,
73 'XSETBV': 55,
74 'APIC_WRITE': 56,
75 'INVPCID': 58,
76}
77
78SVM_EXIT_REASONS = {
79 'READ_CR0': 0x000,
80 'READ_CR3': 0x003,
81 'READ_CR4': 0x004,
82 'READ_CR8': 0x008,
83 'WRITE_CR0': 0x010,
84 'WRITE_CR3': 0x013,
85 'WRITE_CR4': 0x014,
86 'WRITE_CR8': 0x018,
87 'READ_DR0': 0x020,
88 'READ_DR1': 0x021,
89 'READ_DR2': 0x022,
90 'READ_DR3': 0x023,
91 'READ_DR4': 0x024,
92 'READ_DR5': 0x025,
93 'READ_DR6': 0x026,
94 'READ_DR7': 0x027,
95 'WRITE_DR0': 0x030,
96 'WRITE_DR1': 0x031,
97 'WRITE_DR2': 0x032,
98 'WRITE_DR3': 0x033,
99 'WRITE_DR4': 0x034,
100 'WRITE_DR5': 0x035,
101 'WRITE_DR6': 0x036,
102 'WRITE_DR7': 0x037,
103 'EXCP_BASE': 0x040,
104 'INTR': 0x060,
105 'NMI': 0x061,
106 'SMI': 0x062,
107 'INIT': 0x063,
108 'VINTR': 0x064,
109 'CR0_SEL_WRITE': 0x065,
110 'IDTR_READ': 0x066,
111 'GDTR_READ': 0x067,
112 'LDTR_READ': 0x068,
113 'TR_READ': 0x069,
114 'IDTR_WRITE': 0x06a,
115 'GDTR_WRITE': 0x06b,
116 'LDTR_WRITE': 0x06c,
117 'TR_WRITE': 0x06d,
118 'RDTSC': 0x06e,
119 'RDPMC': 0x06f,
120 'PUSHF': 0x070,
121 'POPF': 0x071,
122 'CPUID': 0x072,
123 'RSM': 0x073,
124 'IRET': 0x074,
125 'SWINT': 0x075,
126 'INVD': 0x076,
127 'PAUSE': 0x077,
128 'HLT': 0x078,
129 'INVLPG': 0x079,
130 'INVLPGA': 0x07a,
131 'IOIO': 0x07b,
132 'MSR': 0x07c,
133 'TASK_SWITCH': 0x07d,
134 'FERR_FREEZE': 0x07e,
135 'SHUTDOWN': 0x07f,
136 'VMRUN': 0x080,
137 'VMMCALL': 0x081,
138 'VMLOAD': 0x082,
139 'VMSAVE': 0x083,
140 'STGI': 0x084,
141 'CLGI': 0x085,
142 'SKINIT': 0x086,
143 'RDTSCP': 0x087,
144 'ICEBP': 0x088,
145 'WBINVD': 0x089,
146 'MONITOR': 0x08a,
147 'MWAIT': 0x08b,
148 'MWAIT_COND': 0x08c,
149 'XSETBV': 0x08d,
150 'NPF': 0x400,
151}
152
153# EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h)
154AARCH64_EXIT_REASONS = {
155 'UNKNOWN': 0x00,
156 'WFI': 0x01,
157 'CP15_32': 0x03,
158 'CP15_64': 0x04,
159 'CP14_MR': 0x05,
160 'CP14_LS': 0x06,
161 'FP_ASIMD': 0x07,
162 'CP10_ID': 0x08,
163 'CP14_64': 0x0C,
164 'ILL_ISS': 0x0E,
165 'SVC32': 0x11,
166 'HVC32': 0x12,
167 'SMC32': 0x13,
168 'SVC64': 0x15,
169 'HVC64': 0x16,
170 'SMC64': 0x17,
171 'SYS64': 0x18,
172 'IABT': 0x20,
173 'IABT_HYP': 0x21,
174 'PC_ALIGN': 0x22,
175 'DABT': 0x24,
176 'DABT_HYP': 0x25,
177 'SP_ALIGN': 0x26,
178 'FP_EXC32': 0x28,
179 'FP_EXC64': 0x2C,
180 'SERROR': 0x2F,
181 'BREAKPT': 0x30,
182 'BREAKPT_HYP': 0x31,
183 'SOFTSTP': 0x32,
184 'SOFTSTP_HYP': 0x33,
185 'WATCHPT': 0x34,
186 'WATCHPT_HYP': 0x35,
187 'BKPT32': 0x38,
188 'VECTOR32': 0x3A,
189 'BRK64': 0x3C,
190}
191
192# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
193USERSPACE_EXIT_REASONS = {
194 'UNKNOWN': 0,
195 'EXCEPTION': 1,
196 'IO': 2,
197 'HYPERCALL': 3,
198 'DEBUG': 4,
199 'HLT': 5,
200 'MMIO': 6,
201 'IRQ_WINDOW_OPEN': 7,
202 'SHUTDOWN': 8,
203 'FAIL_ENTRY': 9,
204 'INTR': 10,
205 'SET_TPR': 11,
206 'TPR_ACCESS': 12,
207 'S390_SIEIC': 13,
208 'S390_RESET': 14,
209 'DCR': 15,
210 'NMI': 16,
211 'INTERNAL_ERROR': 17,
212 'OSI': 18,
213 'PAPR_HCALL': 19,
214 'S390_UCONTROL': 20,
215 'WATCHDOG': 21,
216 'S390_TSCH': 22,
217 'EPR': 23,
218 'SYSTEM_EVENT': 24,
219}
220
221IOCTL_NUMBERS = {
222 'SET_FILTER': 0x40082406,
223 'ENABLE': 0x00002400,
224 'DISABLE': 0x00002401,
225 'RESET': 0x00002403,
226}
227
228class Arch(object):
229 """Encapsulates global architecture specific data.
230
231 Contains the performance event open syscall and ioctl numbers, as
232 well as the VM exit reasons for the architecture it runs on.
233
234 """
235 @staticmethod
236 def get_arch():
237 machine = os.uname()[4]
238
239 if machine.startswith('ppc'):
240 return ArchPPC()
241 elif machine.startswith('aarch64'):
242 return ArchA64()
243 elif machine.startswith('s390'):
244 return ArchS390()
245 else:
246 # X86_64
247 for line in open('/proc/cpuinfo'):
248 if not line.startswith('flags'):
249 continue
250
251 flags = line.split()
252 if 'vmx' in flags:
253 return ArchX86(VMX_EXIT_REASONS)
254 if 'svm' in flags:
255 return ArchX86(SVM_EXIT_REASONS)
256 return
257
258class ArchX86(Arch):
259 def __init__(self, exit_reasons):
260 self.sc_perf_evt_open = 298
261 self.ioctl_numbers = IOCTL_NUMBERS
262 self.exit_reasons = exit_reasons
263
264class ArchPPC(Arch):
265 def __init__(self):
266 self.sc_perf_evt_open = 319
267 self.ioctl_numbers = IOCTL_NUMBERS
268 self.ioctl_numbers['ENABLE'] = 0x20002400
269 self.ioctl_numbers['DISABLE'] = 0x20002401
270 self.ioctl_numbers['RESET'] = 0x20002403
271
272 # PPC comes in 32 and 64 bit and some generated ioctl
273 # numbers depend on the wordsize.
274 char_ptr_size = ctypes.sizeof(ctypes.c_char_p)
275 self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16
276 self.exit_reasons = {}
277
278class ArchA64(Arch):
279 def __init__(self):
280 self.sc_perf_evt_open = 241
281 self.ioctl_numbers = IOCTL_NUMBERS
282 self.exit_reasons = AARCH64_EXIT_REASONS
283
284class ArchS390(Arch):
285 def __init__(self):
286 self.sc_perf_evt_open = 331
287 self.ioctl_numbers = IOCTL_NUMBERS
288 self.exit_reasons = None
289
290ARCH = Arch.get_arch()
291
292
293def walkdir(path):
294 """Returns os.walk() data for specified directory.
295
296 As it is only a wrapper it returns the same 3-tuple of (dirpath,
297 dirnames, filenames).
298 """
299 return next(os.walk(path))
300
301
302def parse_int_list(list_string):
303 """Returns an int list from a string of comma separated integers and
304 integer ranges."""
305 integers = []
306 members = list_string.split(',')
307
308 for member in members:
309 if '-' not in member:
310 integers.append(int(member))
311 else:
312 int_range = member.split('-')
313 integers.extend(range(int(int_range[0]),
314 int(int_range[1]) + 1))
315
316 return integers
317
318
319def get_online_cpus():
320 """Returns a list of cpu id integers."""
321 with open('/sys/devices/system/cpu/online') as cpu_list:
322 cpu_string = cpu_list.readline()
323 return parse_int_list(cpu_string)
324
325
326def get_filters():
327 """Returns a dict of trace events, their filter ids and
328 the values that can be filtered.
329
330 Trace events can be filtered for special values by setting a
331 filter string via an ioctl. The string normally has the format
332 identifier==value. For each filter a new event will be created, to
333 be able to distinguish the events.
334
335 """
336 filters = {}
337 filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
338 if ARCH.exit_reasons:
339 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
340 return filters
341
342libc = ctypes.CDLL('libc.so.6', use_errno=True)
343syscall = libc.syscall
344
345class perf_event_attr(ctypes.Structure):
346 """Struct that holds the necessary data to set up a trace event.
347
348 For an extensive explanation see perf_event_open(2) and
349 include/uapi/linux/perf_event.h, struct perf_event_attr
350
351 All fields that are not initialized in the constructor are 0.
352
353 """
354 _fields_ = [('type', ctypes.c_uint32),
355 ('size', ctypes.c_uint32),
356 ('config', ctypes.c_uint64),
357 ('sample_freq', ctypes.c_uint64),
358 ('sample_type', ctypes.c_uint64),
359 ('read_format', ctypes.c_uint64),
360 ('flags', ctypes.c_uint64),
361 ('wakeup_events', ctypes.c_uint32),
362 ('bp_type', ctypes.c_uint32),
363 ('bp_addr', ctypes.c_uint64),
364 ('bp_len', ctypes.c_uint64),
365 ]
366
367 def __init__(self):
368 super(self.__class__, self).__init__()
369 self.type = PERF_TYPE_TRACEPOINT
370 self.size = ctypes.sizeof(self)
371 self.read_format = PERF_FORMAT_GROUP
372
373def perf_event_open(attr, pid, cpu, group_fd, flags):
374 """Wrapper for the sys_perf_evt_open() syscall.
375
376 Used to set up performance events, returns a file descriptor or -1
377 on error.
378
379 Attributes are:
380 - syscall number
381 - struct perf_event_attr *
382 - pid or -1 to monitor all pids
383 - cpu number or -1 to monitor all cpus
384 - The file descriptor of the group leader or -1 to create a group.
385 - flags
386
387 """
388 return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
389 ctypes.c_int(pid), ctypes.c_int(cpu),
390 ctypes.c_int(group_fd), ctypes.c_long(flags))
391
392PERF_TYPE_TRACEPOINT = 2
393PERF_FORMAT_GROUP = 1 << 3
394
395PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
396PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
397
398class Group(object):
399 """Represents a perf event group."""
400
401 def __init__(self):
402 self.events = []
403
404 def add_event(self, event):
405 self.events.append(event)
406
407 def read(self):
408 """Returns a dict with 'event name: value' for all events in the
409 group.
410
411 Values are read by reading from the file descriptor of the
412 event that is the group leader. See perf_event_open(2) for
413 details.
414
415 Read format for the used event configuration is:
416 struct read_format {
417 u64 nr; /* The number of events */
418 struct {
419 u64 value; /* The value of the event */
420 } values[nr];
421 };
422
423 """
424 length = 8 * (1 + len(self.events))
425 read_format = 'xxxxxxxx' + 'Q' * len(self.events)
426 return dict(zip([event.name for event in self.events],
427 struct.unpack(read_format,
428 os.read(self.events[0].fd, length))))
429
430class Event(object):
431 """Represents a performance event and manages its life cycle."""
432 def __init__(self, name, group, trace_cpu, trace_pid, trace_point,
433 trace_filter, trace_set='kvm'):
434 self.name = name
435 self.fd = None
436 self.setup_event(group, trace_cpu, trace_pid, trace_point,
437 trace_filter, trace_set)
438
439 def __del__(self):
440 """Closes the event's file descriptor.
441
442 As no python file object was created for the file descriptor,
443 python will not reference count the descriptor and will not
444 close it itself automatically, so we do it.
445
446 """
447 if self.fd:
448 os.close(self.fd)
449
450 def setup_event_attribute(self, trace_set, trace_point):
451 """Returns an initialized ctype perf_event_attr struct."""
452
453 id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set,
454 trace_point, 'id')
455
456 event_attr = perf_event_attr()
457 event_attr.config = int(open(id_path).read())
458 return event_attr
459
460 def setup_event(self, group, trace_cpu, trace_pid, trace_point,
461 trace_filter, trace_set):
462 """Sets up the perf event in Linux.
463
464 Issues the syscall to register the event in the kernel and
465 then sets the optional filter.
466
467 """
468
469 event_attr = self.setup_event_attribute(trace_set, trace_point)
470
471 # First event will be group leader.
472 group_leader = -1
473
474 # All others have to pass the leader's descriptor instead.
475 if group.events:
476 group_leader = group.events[0].fd
477
478 fd = perf_event_open(event_attr, trace_pid,
479 trace_cpu, group_leader, 0)
480 if fd == -1:
481 err = ctypes.get_errno()
482 raise OSError(err, os.strerror(err),
483 'while calling sys_perf_event_open().')
484
485 if trace_filter:
486 fcntl.ioctl(fd, ARCH.ioctl_numbers['SET_FILTER'],
487 trace_filter)
488
489 self.fd = fd
490
491 def enable(self):
492 """Enables the trace event in the kernel.
493
494 Enabling the group leader makes reading counters from it and the
495 events under it possible.
496
497 """
498 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['ENABLE'], 0)
499
500 def disable(self):
501 """Disables the trace event in the kernel.
502
503 Disabling the group leader makes reading all counters under it
504 impossible.
505
506 """
507 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['DISABLE'], 0)
508
509 def reset(self):
510 """Resets the count of the trace event in the kernel."""
511 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0)
512
513class TracepointProvider(object):
514 """Data provider for the stats class.
515
516 Manages the events/groups from which it acquires its data.
517
518 """
519 def __init__(self):
520 self.group_leaders = []
521 self.filters = get_filters()
522 self._fields = self.get_available_fields()
523 self._pid = 0
524
525 def get_available_fields(self):
526 """Returns a list of available event's of format 'event name(filter
527 name)'.
528
529 All available events have directories under
530 /sys/kernel/debug/tracing/events/ which export information
531 about the specific event. Therefore, listing the dirs gives us
532 a list of all available events.
533
534 Some events like the vm exit reasons can be filtered for
535 specific values. To take account for that, the routine below
536 creates special fields with the following format:
537 event name(filter name)
538
539 """
540 path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
541 fields = walkdir(path)[1]
542 extra = []
543 for field in fields:
544 if field in self.filters:
545 filter_name_, filter_dicts = self.filters[field]
546 for name in filter_dicts:
547 extra.append(field + '(' + name + ')')
548 fields += extra
549 return fields
550
551 def setup_traces(self):
552 """Creates all event and group objects needed to be able to retrieve
553 data."""
554 if self._pid > 0:
555 # Fetch list of all threads of the monitored pid, as qemu
556 # starts a thread for each vcpu.
557 path = os.path.join('/proc', str(self._pid), 'task')
558 groupids = walkdir(path)[1]
559 else:
560 groupids = get_online_cpus()
561
562 # The constant is needed as a buffer for python libs, std
563 # streams and other files that the script opens.
564 newlim = len(groupids) * len(self._fields) + 50
565 try:
566 softlim_, hardlim = resource.getrlimit(resource.RLIMIT_NOFILE)
567
568 if hardlim < newlim:
569 # Now we need CAP_SYS_RESOURCE, to increase the hard limit.
570 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, newlim))
571 else:
572 # Raising the soft limit is sufficient.
573 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, hardlim))
574
575 except ValueError:
576 sys.exit("NOFILE rlimit could not be raised to {0}".format(newlim))
577
578 for groupid in groupids:
579 group = Group()
580 for name in self._fields:
581 tracepoint = name
582 tracefilter = None
583 match = re.match(r'(.*)\((.*)\)', name)
584 if match:
585 tracepoint, sub = match.groups()
586 tracefilter = ('%s==%d\0' %
587 (self.filters[tracepoint][0],
588 self.filters[tracepoint][1][sub]))
589
590 # From perf_event_open(2):
591 # pid > 0 and cpu == -1
592 # This measures the specified process/thread on any CPU.
593 #
594 # pid == -1 and cpu >= 0
595 # This measures all processes/threads on the specified CPU.
596 trace_cpu = groupid if self._pid == 0 else -1
597 trace_pid = int(groupid) if self._pid != 0 else -1
598
599 group.add_event(Event(name=name,
600 group=group,
601 trace_cpu=trace_cpu,
602 trace_pid=trace_pid,
603 trace_point=tracepoint,
604 trace_filter=tracefilter))
605
606 self.group_leaders.append(group)
607
608 def available_fields(self):
609 return self.get_available_fields()
610
611 @property
612 def fields(self):
613 return self._fields
614
615 @fields.setter
616 def fields(self, fields):
617 """Enables/disables the (un)wanted events"""
618 self._fields = fields
619 for group in self.group_leaders:
620 for index, event in enumerate(group.events):
621 if event.name in fields:
622 event.reset()
623 event.enable()
624 else:
625 # Do not disable the group leader.
626 # It would disable all of its events.
627 if index != 0:
628 event.disable()
629
630 @property
631 def pid(self):
632 return self._pid
633
634 @pid.setter
635 def pid(self, pid):
636 """Changes the monitored pid by setting new traces."""
637 self._pid = pid
638 # The garbage collector will get rid of all Event/Group
639 # objects and open files after removing the references.
640 self.group_leaders = []
641 self.setup_traces()
642 self.fields = self._fields
643
644 def read(self):
645 """Returns 'event name: current value' for all enabled events."""
646 ret = defaultdict(int)
647 for group in self.group_leaders:
648 for name, val in group.read().iteritems():
649 if name in self._fields:
650 ret[name] += val
651 return ret
652
653class DebugfsProvider(object):
654 """Provides data from the files that KVM creates in the kvm debugfs
655 folder."""
656 def __init__(self):
657 self._fields = self.get_available_fields()
658 self._pid = 0
659 self.do_read = True
660
661 def get_available_fields(self):
662 """"Returns a list of available fields.
663
664 The fields are all available KVM debugfs files
665
666 """
667 return walkdir(PATH_DEBUGFS_KVM)[2]
668
669 @property
670 def fields(self):
671 return self._fields
672
673 @fields.setter
674 def fields(self, fields):
675 self._fields = fields
676
677 @property
678 def pid(self):
679 return self._pid
680
681 @pid.setter
682 def pid(self, pid):
683 if pid != 0:
684 self._pid = pid
685
686 vms = walkdir(PATH_DEBUGFS_KVM)[1]
687 if len(vms) == 0:
688 self.do_read = False
689
690 self.paths = filter(lambda x: "{}-".format(pid) in x, vms)
691
692 else:
693 self.paths = ['']
694 self.do_read = True
695
696 def read(self):
697 """Returns a dict with format:'file name / field -> current value'."""
698 results = {}
699
700 # If no debugfs filtering support is available, then don't read.
701 if not self.do_read:
702 return results
703
704 for path in self.paths:
705 for field in self._fields:
706 results[field] = results.get(field, 0) \
707 + self.read_field(field, path)
708
709 return results
710
711 def read_field(self, field, path):
712 """Returns the value of a single field from a specific VM."""
713 try:
714 return int(open(os.path.join(PATH_DEBUGFS_KVM,
715 path,
716 field))
717 .read())
718 except IOError:
719 return 0
720
721class Stats(object):
722 """Manages the data providers and the data they provide.
723
724 It is used to set filters on the provider's data and collect all
725 provider data.
726
727 """
728 def __init__(self, providers, pid, fields=None):
729 self.providers = providers
730 self._pid_filter = pid
731 self._fields_filter = fields
732 self.values = {}
733 self.update_provider_pid()
734 self.update_provider_filters()
735
736 def update_provider_filters(self):
737 """Propagates fields filters to providers."""
738 def wanted(key):
739 if not self._fields_filter:
740 return True
741 return re.match(self._fields_filter, key) is not None
742
743 # As we reset the counters when updating the fields we can
744 # also clear the cache of old values.
745 self.values = {}
746 for provider in self.providers:
747 provider_fields = [key for key in provider.get_available_fields()
748 if wanted(key)]
749 provider.fields = provider_fields
750
751 def update_provider_pid(self):
752 """Propagates pid filters to providers."""
753 for provider in self.providers:
754 provider.pid = self._pid_filter
755
756 @property
757 def fields_filter(self):
758 return self._fields_filter
759
760 @fields_filter.setter
761 def fields_filter(self, fields_filter):
762 self._fields_filter = fields_filter
763 self.update_provider_filters()
764
765 @property
766 def pid_filter(self):
767 return self._pid_filter
768
769 @pid_filter.setter
770 def pid_filter(self, pid):
771 self._pid_filter = pid
772 self.values = {}
773 self.update_provider_pid()
774
775 def get(self):
776 """Returns a dict with field -> (value, delta to last value) of all
777 provider data."""
778 for provider in self.providers:
779 new = provider.read()
780 for key in provider.fields:
781 oldval = self.values.get(key, (0, 0))
782 newval = new.get(key, 0)
783 newdelta = None
784 if oldval is not None:
785 newdelta = newval - oldval[0]
786 self.values[key] = (newval, newdelta)
787 return self.values
788
789LABEL_WIDTH = 40
790NUMBER_WIDTH = 10
791
792class Tui(object):
793 """Instruments curses to draw a nice text ui."""
794 def __init__(self, stats):
795 self.stats = stats
796 self.screen = None
797 self.drilldown = False
798 self.update_drilldown()
799
800 def __enter__(self):
801 """Initialises curses for later use. Based on curses.wrapper
802 implementation from the Python standard library."""
803 self.screen = curses.initscr()
804 curses.noecho()
805 curses.cbreak()
806
807 # The try/catch works around a minor bit of
808 # over-conscientiousness in the curses module, the error
809 # return from C start_color() is ignorable.
810 try:
811 curses.start_color()
812 except:
813 pass
814
815 curses.use_default_colors()
816 return self
817
818 def __exit__(self, *exception):
819 """Resets the terminal to its normal state. Based on curses.wrappre
820 implementation from the Python standard library."""
821 if self.screen:
822 self.screen.keypad(0)
823 curses.echo()
824 curses.nocbreak()
825 curses.endwin()
826
827 def update_drilldown(self):
828 """Sets or removes a filter that only allows fields without braces."""
829 if not self.stats.fields_filter:
830 self.stats.fields_filter = r'^[^\(]*$'
831
832 elif self.stats.fields_filter == r'^[^\(]*$':
833 self.stats.fields_filter = None
834
835 def update_pid(self, pid):
836 """Propagates pid selection to stats object."""
837 self.stats.pid_filter = pid
838
839 def refresh(self, sleeptime):
840 """Refreshes on-screen data."""
841 self.screen.erase()
842 if self.stats.pid_filter > 0:
843 self.screen.addstr(0, 0, 'kvm statistics - pid {0}'
844 .format(self.stats.pid_filter),
845 curses.A_BOLD)
846 else:
847 self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
848 self.screen.addstr(2, 1, 'Event')
849 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH -
850 len('Total'), 'Total')
851 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 -
852 len('Current'), 'Current')
853 row = 3
854 stats = self.stats.get()
855 def sortkey(x):
856 if stats[x][1]:
857 return (-stats[x][1], -stats[x][0])
858 else:
859 return (0, -stats[x][0])
860 for key in sorted(stats.keys(), key=sortkey):
861
862 if row >= self.screen.getmaxyx()[0]:
863 break
864 values = stats[key]
865 if not values[0] and not values[1]:
866 break
867 col = 1
868 self.screen.addstr(row, col, key)
869 col += LABEL_WIDTH
870 self.screen.addstr(row, col, '%10d' % (values[0],))
871 col += NUMBER_WIDTH
872 if values[1] is not None:
873 self.screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
874 row += 1
875 self.screen.refresh()
876
877 def show_filter_selection(self):
878 """Draws filter selection mask.
879
880 Asks for a valid regex and sets the fields filter accordingly.
881
882 """
883 while True:
884 self.screen.erase()
885 self.screen.addstr(0, 0,
886 "Show statistics for events matching a regex.",
887 curses.A_BOLD)
888 self.screen.addstr(2, 0,
889 "Current regex: {0}"
890 .format(self.stats.fields_filter))
891 self.screen.addstr(3, 0, "New regex: ")
892 curses.echo()
893 regex = self.screen.getstr()
894 curses.noecho()
895 if len(regex) == 0:
896 return
897 try:
898 re.compile(regex)
899 self.stats.fields_filter = regex
900 return
901 except re.error:
902 continue
903
904 def show_vm_selection(self):
905 """Draws PID selection mask.
906
907 Asks for a pid until a valid pid or 0 has been entered.
908
909 """
910 while True:
911 self.screen.erase()
912 self.screen.addstr(0, 0,
913 'Show statistics for specific pid.',
914 curses.A_BOLD)
915 self.screen.addstr(1, 0,
916 'This might limit the shown data to the trace '
917 'statistics.')
918
919 curses.echo()
920 self.screen.addstr(3, 0, "Pid [0 or pid]: ")
921 pid = self.screen.getstr()
922 curses.noecho()
923
924 try:
925 pid = int(pid)
926
927 if pid == 0:
928 self.update_pid(pid)
929 break
930 else:
931 if not os.path.isdir(os.path.join('/proc/', str(pid))):
932 continue
933 else:
934 self.update_pid(pid)
935 break
936
937 except ValueError:
938 continue
939
940 def show_stats(self):
941 """Refreshes the screen and processes user input."""
942 sleeptime = 0.25
943 while True:
944 self.refresh(sleeptime)
945 curses.halfdelay(int(sleeptime * 10))
946 sleeptime = 3
947 try:
948 char = self.screen.getkey()
949 if char == 'x':
950 self.drilldown = not self.drilldown
951 self.update_drilldown()
952 if char == 'q':
953 break
954 if char == 'f':
955 self.show_filter_selection()
956 if char == 'p':
957 self.show_vm_selection()
958 except KeyboardInterrupt:
959 break
960 except curses.error:
961 continue
962
963def batch(stats):
964 """Prints statistics in a key, value format."""
965 s = stats.get()
966 time.sleep(1)
967 s = stats.get()
968 for key in sorted(s.keys()):
969 values = s[key]
970 print '%-42s%10d%10d' % (key, values[0], values[1])
971
972def log(stats):
973 """Prints statistics as reiterating key block, multiple value blocks."""
974 keys = sorted(stats.get().iterkeys())
975 def banner():
976 for k in keys:
977 print '%s' % k,
978 print
979 def statline():
980 s = stats.get()
981 for k in keys:
982 print ' %9d' % s[k][1],
983 print
984 line = 0
985 banner_repeat = 20
986 while True:
987 time.sleep(1)
988 if line % banner_repeat == 0:
989 banner()
990 statline()
991 line += 1
992
993def get_options():
994 """Returns processed program arguments."""
995 description_text = """
996This script displays various statistics about VMs running under KVM.
997The statistics are gathered from the KVM debugfs entries and / or the
998currently available perf traces.
999
1000The monitoring takes additional cpu cycles and might affect the VM's
1001performance.
1002
1003Requirements:
1004- Access to:
1005 /sys/kernel/debug/kvm
1006 /sys/kernel/debug/trace/events/*
1007 /proc/pid/task
1008- /proc/sys/kernel/perf_event_paranoid < 1 if user has no
1009 CAP_SYS_ADMIN and perf events are used.
1010- CAP_SYS_RESOURCE if the hard limit is not high enough to allow
1011 the large number of files that are possibly opened.
1012"""
1013
1014 class PlainHelpFormatter(optparse.IndentedHelpFormatter):
1015 def format_description(self, description):
1016 if description:
1017 return description + "\n"
1018 else:
1019 return ""
1020
1021 optparser = optparse.OptionParser(description=description_text,
1022 formatter=PlainHelpFormatter())
1023 optparser.add_option('-1', '--once', '--batch',
1024 action='store_true',
1025 default=False,
1026 dest='once',
1027 help='run in batch mode for one second',
1028 )
1029 optparser.add_option('-l', '--log',
1030 action='store_true',
1031 default=False,
1032 dest='log',
1033 help='run in logging mode (like vmstat)',
1034 )
1035 optparser.add_option('-t', '--tracepoints',
1036 action='store_true',
1037 default=False,
1038 dest='tracepoints',
1039 help='retrieve statistics from tracepoints',
1040 )
1041 optparser.add_option('-d', '--debugfs',
1042 action='store_true',
1043 default=False,
1044 dest='debugfs',
1045 help='retrieve statistics from debugfs',
1046 )
1047 optparser.add_option('-f', '--fields',
1048 action='store',
1049 default=None,
1050 dest='fields',
1051 help='fields to display (regex)',
1052 )
1053 optparser.add_option('-p', '--pid',
1054 action='store',
1055 default=0,
1056 type=int,
1057 dest='pid',
1058 help='restrict statistics to pid',
1059 )
1060 (options, _) = optparser.parse_args(sys.argv)
1061 return options
1062
1063def get_providers(options):
1064 """Returns a list of data providers depending on the passed options."""
1065 providers = []
1066
1067 if options.tracepoints:
1068 providers.append(TracepointProvider())
1069 if options.debugfs:
1070 providers.append(DebugfsProvider())
1071 if len(providers) == 0:
1072 providers.append(TracepointProvider())
1073
1074 return providers
1075
1076def check_access(options):
1077 """Exits if the current user can't access all needed directories."""
1078 if not os.path.exists('/sys/kernel/debug'):
1079 sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.')
1080 sys.exit(1)
1081
1082 if not os.path.exists(PATH_DEBUGFS_KVM):
1083 sys.stderr.write("Please make sure, that debugfs is mounted and "
1084 "readable by the current user:\n"
1085 "('mount -t debugfs debugfs /sys/kernel/debug')\n"
1086 "Also ensure, that the kvm modules are loaded.\n")
1087 sys.exit(1)
1088
1089 if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints
1090 or not options.debugfs):
1091 sys.stderr.write("Please enable CONFIG_TRACING in your kernel "
1092 "when using the option -t (default).\n"
1093 "If it is enabled, make {0} readable by the "
1094 "current user.\n"
1095 .format(PATH_DEBUGFS_TRACING))
1096 if options.tracepoints:
1097 sys.exit(1)
1098
1099 sys.stderr.write("Falling back to debugfs statistics!\n")
1100 options.debugfs = True
1101 sleep(5)
1102
1103 return options
1104
1105def main():
1106 options = get_options()
1107 options = check_access(options)
1108
1109 if (options.pid > 0 and
1110 not os.path.isdir(os.path.join('/proc/',
1111 str(options.pid)))):
1112 sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n')
1113 sys.exit('Specified pid does not exist.')
1114
1115 providers = get_providers(options)
1116 stats = Stats(providers, options.pid, fields=options.fields)
1117
1118 if options.log:
1119 log(stats)
1120 elif not options.once:
1121 with Tui(stats) as tui:
1122 tui.show_stats()
1123 else:
1124 batch(stats)
1125
1126if __name__ == "__main__":
1127 main()
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
new file mode 100644
index 000000000000..b92a153d7115
--- /dev/null
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -0,0 +1,63 @@
1kvm_stat(1)
2===========
3
4NAME
5----
6kvm_stat - Report KVM kernel module event counters
7
8SYNOPSIS
9--------
10[verse]
11'kvm_stat' [OPTION]...
12
13DESCRIPTION
14-----------
15kvm_stat prints counts of KVM kernel module trace events. These events signify
16state transitions such as guest mode entry and exit.
17
18This tool is useful for observing guest behavior from the host perspective.
19Often conclusions about performance or buggy behavior can be drawn from the
20output.
21
22The set of KVM kernel module trace events may be specific to the kernel version
23or architecture. It is best to check the KVM kernel module source code for the
24meaning of events.
25
26OPTIONS
27-------
28-1::
29--once::
30--batch::
31 run in batch mode for one second
32
33-l::
34--log::
35 run in logging mode (like vmstat)
36
37-t::
38--tracepoints::
39 retrieve statistics from tracepoints
40
41-d::
42--debugfs::
43 retrieve statistics from debugfs
44
45-p<pid>::
46--pid=<pid>::
47 limit statistics to one virtual machine (pid)
48
49-f<fields>::
50--fields=<fields>::
51 fields to display (regex)
52
53-h::
54--help::
55 show help message
56
57SEE ALSO
58--------
59'perf'(1), 'trace-cmd'(1)
60
61AUTHOR
62------
63Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 6765c7e949f3..f094f3c4ed84 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -30,6 +30,10 @@ INCLUDES := -I$(srctree)/tools/include
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD) 31LDFLAGS += -lelf $(LIBSUBCMD)
32 32
33# Allow old libelf to be used:
34elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
35CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
36
33AWK = awk 37AWK = awk
34export srctree OUTPUT CFLAGS ARCH AWK 38export srctree OUTPUT CFLAGS ARCH AWK
35include $(srctree)/tools/build/Makefile.include 39include $(srctree)/tools/build/Makefile.include
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 7f3e00a2f907..aa1ff6596684 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -23,6 +23,11 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/hashtable.h> 24#include <linux/hashtable.h>
25 25
26#ifdef LIBELF_USE_DEPRECATED
27# define elf_getshdrnum elf_getshnum
28# define elf_getshdrstrndx elf_getshstrndx
29#endif
30
26struct section { 31struct section {
27 struct list_head list; 32 struct list_head list;
28 GElf_Shdr sh; 33 GElf_Shdr sh;
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
new file mode 100644
index 000000000000..75de0e92e71e
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -0,0 +1,69 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <asm/perf_regs.h>
7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__
11 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
12#else
13 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
14#endif
15
16#define PERF_REG_IP PERF_REG_POWERPC_NIP
17#define PERF_REG_SP PERF_REG_POWERPC_R1
18
19static const char *reg_names[] = {
20 [PERF_REG_POWERPC_R0] = "r0",
21 [PERF_REG_POWERPC_R1] = "r1",
22 [PERF_REG_POWERPC_R2] = "r2",
23 [PERF_REG_POWERPC_R3] = "r3",
24 [PERF_REG_POWERPC_R4] = "r4",
25 [PERF_REG_POWERPC_R5] = "r5",
26 [PERF_REG_POWERPC_R6] = "r6",
27 [PERF_REG_POWERPC_R7] = "r7",
28 [PERF_REG_POWERPC_R8] = "r8",
29 [PERF_REG_POWERPC_R9] = "r9",
30 [PERF_REG_POWERPC_R10] = "r10",
31 [PERF_REG_POWERPC_R11] = "r11",
32 [PERF_REG_POWERPC_R12] = "r12",
33 [PERF_REG_POWERPC_R13] = "r13",
34 [PERF_REG_POWERPC_R14] = "r14",
35 [PERF_REG_POWERPC_R15] = "r15",
36 [PERF_REG_POWERPC_R16] = "r16",
37 [PERF_REG_POWERPC_R17] = "r17",
38 [PERF_REG_POWERPC_R18] = "r18",
39 [PERF_REG_POWERPC_R19] = "r19",
40 [PERF_REG_POWERPC_R20] = "r20",
41 [PERF_REG_POWERPC_R21] = "r21",
42 [PERF_REG_POWERPC_R22] = "r22",
43 [PERF_REG_POWERPC_R23] = "r23",
44 [PERF_REG_POWERPC_R24] = "r24",
45 [PERF_REG_POWERPC_R25] = "r25",
46 [PERF_REG_POWERPC_R26] = "r26",
47 [PERF_REG_POWERPC_R27] = "r27",
48 [PERF_REG_POWERPC_R28] = "r28",
49 [PERF_REG_POWERPC_R29] = "r29",
50 [PERF_REG_POWERPC_R30] = "r30",
51 [PERF_REG_POWERPC_R31] = "r31",
52 [PERF_REG_POWERPC_NIP] = "nip",
53 [PERF_REG_POWERPC_MSR] = "msr",
54 [PERF_REG_POWERPC_ORIG_R3] = "orig_r3",
55 [PERF_REG_POWERPC_CTR] = "ctr",
56 [PERF_REG_POWERPC_LINK] = "link",
57 [PERF_REG_POWERPC_XER] = "xer",
58 [PERF_REG_POWERPC_CCR] = "ccr",
59 [PERF_REG_POWERPC_SOFTE] = "softe",
60 [PERF_REG_POWERPC_TRAP] = "trap",
61 [PERF_REG_POWERPC_DAR] = "dar",
62 [PERF_REG_POWERPC_DSISR] = "dsisr"
63};
64
65static inline const char *perf_reg_name(int id)
66{
67 return reg_names[id];
68}
69#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index c8fe2074d217..90ad64b231cd 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,6 +1,8 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
4libperf-y += perf_regs.o
4 5
5libperf-$(CONFIG_DWARF) += dwarf-regs.o 6libperf-$(CONFIG_DWARF) += dwarf-regs.o
6libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
8libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
new file mode 100644
index 000000000000..a3c3e1ce6807
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -0,0 +1,49 @@
1#include "../../perf.h"
2#include "../../util/perf_regs.h"
3
4const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(r0, PERF_REG_POWERPC_R0),
6 SMPL_REG(r1, PERF_REG_POWERPC_R1),
7 SMPL_REG(r2, PERF_REG_POWERPC_R2),
8 SMPL_REG(r3, PERF_REG_POWERPC_R3),
9 SMPL_REG(r4, PERF_REG_POWERPC_R4),
10 SMPL_REG(r5, PERF_REG_POWERPC_R5),
11 SMPL_REG(r6, PERF_REG_POWERPC_R6),
12 SMPL_REG(r7, PERF_REG_POWERPC_R7),
13 SMPL_REG(r8, PERF_REG_POWERPC_R8),
14 SMPL_REG(r9, PERF_REG_POWERPC_R9),
15 SMPL_REG(r10, PERF_REG_POWERPC_R10),
16 SMPL_REG(r11, PERF_REG_POWERPC_R11),
17 SMPL_REG(r12, PERF_REG_POWERPC_R12),
18 SMPL_REG(r13, PERF_REG_POWERPC_R13),
19 SMPL_REG(r14, PERF_REG_POWERPC_R14),
20 SMPL_REG(r15, PERF_REG_POWERPC_R15),
21 SMPL_REG(r16, PERF_REG_POWERPC_R16),
22 SMPL_REG(r17, PERF_REG_POWERPC_R17),
23 SMPL_REG(r18, PERF_REG_POWERPC_R18),
24 SMPL_REG(r19, PERF_REG_POWERPC_R19),
25 SMPL_REG(r20, PERF_REG_POWERPC_R20),
26 SMPL_REG(r21, PERF_REG_POWERPC_R21),
27 SMPL_REG(r22, PERF_REG_POWERPC_R22),
28 SMPL_REG(r23, PERF_REG_POWERPC_R23),
29 SMPL_REG(r24, PERF_REG_POWERPC_R24),
30 SMPL_REG(r25, PERF_REG_POWERPC_R25),
31 SMPL_REG(r26, PERF_REG_POWERPC_R26),
32 SMPL_REG(r27, PERF_REG_POWERPC_R27),
33 SMPL_REG(r28, PERF_REG_POWERPC_R28),
34 SMPL_REG(r29, PERF_REG_POWERPC_R29),
35 SMPL_REG(r30, PERF_REG_POWERPC_R30),
36 SMPL_REG(r31, PERF_REG_POWERPC_R31),
37 SMPL_REG(nip, PERF_REG_POWERPC_NIP),
38 SMPL_REG(msr, PERF_REG_POWERPC_MSR),
39 SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
40 SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
41 SMPL_REG(link, PERF_REG_POWERPC_LINK),
42 SMPL_REG(xer, PERF_REG_POWERPC_XER),
43 SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
44 SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
45 SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
46 SMPL_REG(dar, PERF_REG_POWERPC_DAR),
47 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
48 SMPL_REG_END
49};
diff --git a/tools/perf/arch/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c
new file mode 100644
index 000000000000..9e15f92ae49f
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libunwind.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016 Chandan Kumar, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <errno.h>
11#include <libunwind.h>
12#include <asm/perf_regs.h>
13#include "../../util/unwind.h"
14#include "../../util/debug.h"
15
16int libunwind__arch_reg_id(int regnum)
17{
18 switch (regnum) {
19 case UNW_PPC64_R0:
20 return PERF_REG_POWERPC_R0;
21 case UNW_PPC64_R1:
22 return PERF_REG_POWERPC_R1;
23 case UNW_PPC64_R2:
24 return PERF_REG_POWERPC_R2;
25 case UNW_PPC64_R3:
26 return PERF_REG_POWERPC_R3;
27 case UNW_PPC64_R4:
28 return PERF_REG_POWERPC_R4;
29 case UNW_PPC64_R5:
30 return PERF_REG_POWERPC_R5;
31 case UNW_PPC64_R6:
32 return PERF_REG_POWERPC_R6;
33 case UNW_PPC64_R7:
34 return PERF_REG_POWERPC_R7;
35 case UNW_PPC64_R8:
36 return PERF_REG_POWERPC_R8;
37 case UNW_PPC64_R9:
38 return PERF_REG_POWERPC_R9;
39 case UNW_PPC64_R10:
40 return PERF_REG_POWERPC_R10;
41 case UNW_PPC64_R11:
42 return PERF_REG_POWERPC_R11;
43 case UNW_PPC64_R12:
44 return PERF_REG_POWERPC_R12;
45 case UNW_PPC64_R13:
46 return PERF_REG_POWERPC_R13;
47 case UNW_PPC64_R14:
48 return PERF_REG_POWERPC_R14;
49 case UNW_PPC64_R15:
50 return PERF_REG_POWERPC_R15;
51 case UNW_PPC64_R16:
52 return PERF_REG_POWERPC_R16;
53 case UNW_PPC64_R17:
54 return PERF_REG_POWERPC_R17;
55 case UNW_PPC64_R18:
56 return PERF_REG_POWERPC_R18;
57 case UNW_PPC64_R19:
58 return PERF_REG_POWERPC_R19;
59 case UNW_PPC64_R20:
60 return PERF_REG_POWERPC_R20;
61 case UNW_PPC64_R21:
62 return PERF_REG_POWERPC_R21;
63 case UNW_PPC64_R22:
64 return PERF_REG_POWERPC_R22;
65 case UNW_PPC64_R23:
66 return PERF_REG_POWERPC_R23;
67 case UNW_PPC64_R24:
68 return PERF_REG_POWERPC_R24;
69 case UNW_PPC64_R25:
70 return PERF_REG_POWERPC_R25;
71 case UNW_PPC64_R26:
72 return PERF_REG_POWERPC_R26;
73 case UNW_PPC64_R27:
74 return PERF_REG_POWERPC_R27;
75 case UNW_PPC64_R28:
76 return PERF_REG_POWERPC_R28;
77 case UNW_PPC64_R29:
78 return PERF_REG_POWERPC_R29;
79 case UNW_PPC64_R30:
80 return PERF_REG_POWERPC_R30;
81 case UNW_PPC64_R31:
82 return PERF_REG_POWERPC_R31;
83 case UNW_PPC64_LR:
84 return PERF_REG_POWERPC_LINK;
85 case UNW_PPC64_CTR:
86 return PERF_REG_POWERPC_CTR;
87 case UNW_PPC64_XER:
88 return PERF_REG_POWERPC_XER;
89 case UNW_PPC64_NIP:
90 return PERF_REG_POWERPC_NIP;
91 default:
92 pr_err("unwind: invalid reg id %d\n", regnum);
93 return -EINVAL;
94 }
95 return -EINVAL;
96}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1e46277286c2..5ad0255f8756 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,6 +23,12 @@ $(call detected_var,ARCH)
23 23
24NO_PERF_REGS := 1 24NO_PERF_REGS := 1
25 25
26# Additional ARCH settings for ppc
27ifeq ($(ARCH),powerpc)
28 NO_PERF_REGS := 0
29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
30endif
31
26# Additional ARCH settings for x86 32# Additional ARCH settings for x86
27ifeq ($(ARCH),x86) 33ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86) 34 $(call detected,CONFIG_X86)
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 53c2273e8859..ad1cb63139a7 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -73,7 +73,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
73 } 73 }
74 74
75 /* 75 /*
76 * Here we need to explicitely preallocate the counts, as if 76 * Here we need to explicitly preallocate the counts, as if
77 * we use the auto allocation it will allocate just for 1 cpu, 77 * we use the auto allocation it will allocate just for 1 cpu,
78 * as we start by cpu 0. 78 * as we start by cpu 0.
79 */ 79 */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 02c177d14c8d..5d7037ef7d3b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -828,7 +828,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
828 perf_evsel__set_sample_bit(evsel, PERIOD); 828 perf_evsel__set_sample_bit(evsel, PERIOD);
829 829
830 /* 830 /*
831 * When the user explicitely disabled time don't force it here. 831 * When the user explicitly disabled time don't force it here.
832 */ 832 */
833 if (opts->sample_time && 833 if (opts->sample_time &&
834 (!perf_missing_features.sample_id_all && 834 (!perf_missing_features.sample_id_all &&
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 205d27017361..b1772180c820 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -363,7 +363,7 @@ out_err:
363} 363}
364 364
365/* 365/*
366 * Caller must eventually drop thread->refcnt returned with a successfull 366 * Caller must eventually drop thread->refcnt returned with a successful
367 * lookup/new thread inserted. 367 * lookup/new thread inserted.
368 */ 368 */
369static struct thread *____machine__findnew_thread(struct machine *machine, 369static struct thread *____machine__findnew_thread(struct machine *machine,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bcbc983d4b12..c6fd0479f4cd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1649,7 +1649,7 @@ static void parse_events_print_error(struct parse_events_error *err,
1649 1649
1650 buf = _buf; 1650 buf = _buf;
1651 1651
1652 /* We're cutting from the beggining. */ 1652 /* We're cutting from the beginning. */
1653 if (err->idx > max_err_idx) 1653 if (err->idx > max_err_idx)
1654 cut = err->idx - max_err_idx; 1654 cut = err->idx - max_err_idx;
1655 1655
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 6b8eb13e14e4..c4023f22f287 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -12,18 +12,18 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
12 int i, idx = 0; 12 int i, idx = 0;
13 u64 mask = regs->mask; 13 u64 mask = regs->mask;
14 14
15 if (regs->cache_mask & (1 << id)) 15 if (regs->cache_mask & (1ULL << id))
16 goto out; 16 goto out;
17 17
18 if (!(mask & (1 << id))) 18 if (!(mask & (1ULL << id)))
19 return -EINVAL; 19 return -EINVAL;
20 20
21 for (i = 0; i < id; i++) { 21 for (i = 0; i < id; i++) {
22 if (mask & (1 << i)) 22 if (mask & (1ULL << i))
23 idx++; 23 idx++;
24 } 24 }
25 25
26 regs->cache_mask |= (1 << id); 26 regs->cache_mask |= (1ULL << id);
27 regs->cache_regs[id] = regs->regs[idx]; 27 regs->cache_regs[id] = regs->regs[idx];
28 28
29out: 29out:
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 2335b2824d8a..5214974e841a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -557,7 +557,7 @@ static u8 revbyte(u8 b)
557 557
558/* 558/*
559 * XXX this is hack in attempt to carry flags bitfield 559 * XXX this is hack in attempt to carry flags bitfield
560 * throught endian village. ABI says: 560 * through endian village. ABI says:
561 * 561 *
562 * Bit-fields are allocated from right to left (least to most significant) 562 * Bit-fields are allocated from right to left (least to most significant)
563 * on little-endian implementations and from left to right (most to least 563 * on little-endian implementations and from left to right (most to least
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index d0e6b857d8d1..546cf4a503b7 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -91,7 +91,7 @@ osl_get_customized_table(char *pathname,
91 char *signature, 91 char *signature,
92 u32 instance, 92 u32 instance,
93 struct acpi_table_header **table, 93 struct acpi_table_header **table,
94 acpi_physical_address * address); 94 acpi_physical_address *address);
95 95
96static acpi_status osl_list_bios_tables(void); 96static acpi_status osl_list_bios_tables(void);
97 97
@@ -99,7 +99,7 @@ static acpi_status
99osl_get_bios_table(char *signature, 99osl_get_bios_table(char *signature,
100 u32 instance, 100 u32 instance,
101 struct acpi_table_header **table, 101 struct acpi_table_header **table,
102 acpi_physical_address * address); 102 acpi_physical_address *address);
103 103
104static acpi_status osl_get_last_status(acpi_status default_status); 104static acpi_status osl_get_last_status(acpi_status default_status);
105 105
@@ -187,7 +187,7 @@ static acpi_status osl_get_last_status(acpi_status default_status)
187 187
188acpi_status 188acpi_status
189acpi_os_get_table_by_address(acpi_physical_address address, 189acpi_os_get_table_by_address(acpi_physical_address address,
190 struct acpi_table_header ** table) 190 struct acpi_table_header **table)
191{ 191{
192 u32 table_length; 192 u32 table_length;
193 struct acpi_table_header *mapped_table; 193 struct acpi_table_header *mapped_table;
@@ -252,8 +252,8 @@ exit:
252acpi_status 252acpi_status
253acpi_os_get_table_by_name(char *signature, 253acpi_os_get_table_by_name(char *signature,
254 u32 instance, 254 u32 instance,
255 struct acpi_table_header ** table, 255 struct acpi_table_header **table,
256 acpi_physical_address * address) 256 acpi_physical_address *address)
257{ 257{
258 acpi_status status; 258 acpi_status status;
259 259
@@ -380,8 +380,8 @@ static acpi_status osl_add_table_to_list(char *signature, u32 instance)
380 380
381acpi_status 381acpi_status
382acpi_os_get_table_by_index(u32 index, 382acpi_os_get_table_by_index(u32 index,
383 struct acpi_table_header ** table, 383 struct acpi_table_header **table,
384 u32 *instance, acpi_physical_address * address) 384 u32 *instance, acpi_physical_address *address)
385{ 385{
386 struct osl_table_info *info; 386 struct osl_table_info *info;
387 acpi_status status; 387 acpi_status status;
@@ -447,7 +447,7 @@ osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword)
447 } 447 }
448 } 448 }
449 449
450 return ((acpi_physical_address) (address)); 450 return ((acpi_physical_address)(address));
451} 451}
452 452
453/****************************************************************************** 453/******************************************************************************
@@ -751,10 +751,10 @@ static acpi_status osl_list_bios_tables(void)
751 for (i = 0; i < number_of_tables; ++i, table_data += item_size) { 751 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
752 if (osl_can_use_xsdt()) { 752 if (osl_can_use_xsdt()) {
753 table_address = 753 table_address =
754 (acpi_physical_address) (*ACPI_CAST64(table_data)); 754 (acpi_physical_address)(*ACPI_CAST64(table_data));
755 } else { 755 } else {
756 table_address = 756 table_address =
757 (acpi_physical_address) (*ACPI_CAST32(table_data)); 757 (acpi_physical_address)(*ACPI_CAST32(table_data));
758 } 758 }
759 759
760 /* Skip NULL entries in RSDT/XSDT */ 760 /* Skip NULL entries in RSDT/XSDT */
@@ -800,7 +800,7 @@ static acpi_status
800osl_get_bios_table(char *signature, 800osl_get_bios_table(char *signature,
801 u32 instance, 801 u32 instance,
802 struct acpi_table_header **table, 802 struct acpi_table_header **table,
803 acpi_physical_address * address) 803 acpi_physical_address *address)
804{ 804{
805 struct acpi_table_header *local_table = NULL; 805 struct acpi_table_header *local_table = NULL;
806 struct acpi_table_header *mapped_table = NULL; 806 struct acpi_table_header *mapped_table = NULL;
@@ -833,38 +833,37 @@ osl_get_bios_table(char *signature,
833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && 833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
834 gbl_fadt->Xdsdt) { 834 gbl_fadt->Xdsdt) {
835 table_address = 835 table_address =
836 (acpi_physical_address) gbl_fadt->Xdsdt; 836 (acpi_physical_address)gbl_fadt->Xdsdt;
837 } else 837 } else
838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) 838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
839 && gbl_fadt->dsdt) { 839 && gbl_fadt->dsdt) {
840 table_address = 840 table_address =
841 (acpi_physical_address) gbl_fadt->dsdt; 841 (acpi_physical_address)gbl_fadt->dsdt;
842 } 842 }
843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && 844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
845 gbl_fadt->Xfacs) { 845 gbl_fadt->Xfacs) {
846 table_address = 846 table_address =
847 (acpi_physical_address) gbl_fadt->Xfacs; 847 (acpi_physical_address)gbl_fadt->Xfacs;
848 } else 848 } else
849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) 849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
850 && gbl_fadt->facs) { 850 && gbl_fadt->facs) {
851 table_address = 851 table_address =
852 (acpi_physical_address) gbl_fadt->facs; 852 (acpi_physical_address)gbl_fadt->facs;
853 } 853 }
854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { 854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
855 if (!gbl_revision) { 855 if (!gbl_revision) {
856 return (AE_BAD_SIGNATURE); 856 return (AE_BAD_SIGNATURE);
857 } 857 }
858 table_address = 858 table_address =
859 (acpi_physical_address) gbl_rsdp. 859 (acpi_physical_address)gbl_rsdp.
860 xsdt_physical_address; 860 xsdt_physical_address;
861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { 861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
862 table_address = 862 table_address =
863 (acpi_physical_address) gbl_rsdp. 863 (acpi_physical_address)gbl_rsdp.
864 rsdt_physical_address; 864 rsdt_physical_address;
865 } else { 865 } else {
866 table_address = 866 table_address = (acpi_physical_address)gbl_rsdp_address;
867 (acpi_physical_address) gbl_rsdp_address;
868 signature = ACPI_SIG_RSDP; 867 signature = ACPI_SIG_RSDP;
869 } 868 }
870 869
@@ -904,12 +903,12 @@ osl_get_bios_table(char *signature,
904 for (i = 0; i < number_of_tables; ++i, table_data += item_size) { 903 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
905 if (osl_can_use_xsdt()) { 904 if (osl_can_use_xsdt()) {
906 table_address = 905 table_address =
907 (acpi_physical_address) (*ACPI_CAST64 906 (acpi_physical_address)(*ACPI_CAST64
908 (table_data)); 907 (table_data));
909 } else { 908 } else {
910 table_address = 909 table_address =
911 (acpi_physical_address) (*ACPI_CAST32 910 (acpi_physical_address)(*ACPI_CAST32
912 (table_data)); 911 (table_data));
913 } 912 }
914 913
915 /* Skip NULL entries in RSDT/XSDT */ 914 /* Skip NULL entries in RSDT/XSDT */
@@ -1301,7 +1300,7 @@ osl_get_customized_table(char *pathname,
1301 char *signature, 1300 char *signature,
1302 u32 instance, 1301 u32 instance,
1303 struct acpi_table_header **table, 1302 struct acpi_table_header **table,
1304 acpi_physical_address * address) 1303 acpi_physical_address *address)
1305{ 1304{
1306 void *table_dir; 1305 void *table_dir;
1307 u32 current_instance = 0; 1306 u32 current_instance = 0;
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c
index 3818fd07e50f..cbfbce18783d 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixmap.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c
@@ -54,7 +54,7 @@ ACPI_MODULE_NAME("osunixmap")
54#ifndef O_BINARY 54#ifndef O_BINARY
55#define O_BINARY 0 55#define O_BINARY 0
56#endif 56#endif
57#if defined(_dragon_fly) || defined(_free_BSD) 57#if defined(_dragon_fly) || defined(_free_BSD) || defined(_QNX)
58#define MMAP_FLAGS MAP_SHARED 58#define MMAP_FLAGS MAP_SHARED
59#else 59#else
60#define MMAP_FLAGS MAP_PRIVATE 60#define MMAP_FLAGS MAP_PRIVATE
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 08cb8b2035f2..88aa66ef4ad5 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -246,8 +246,8 @@ acpi_physical_address acpi_os_get_root_pointer(void)
246 *****************************************************************************/ 246 *****************************************************************************/
247 247
248acpi_status 248acpi_status
249acpi_os_predefined_override(const struct acpi_predefined_names * init_val, 249acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
250 acpi_string * new_val) 250 acpi_string *new_val)
251{ 251{
252 252
253 if (!init_val || !new_val) { 253 if (!init_val || !new_val) {
@@ -274,8 +274,8 @@ acpi_os_predefined_override(const struct acpi_predefined_names * init_val,
274 *****************************************************************************/ 274 *****************************************************************************/
275 275
276acpi_status 276acpi_status
277acpi_os_table_override(struct acpi_table_header * existing_table, 277acpi_os_table_override(struct acpi_table_header *existing_table,
278 struct acpi_table_header ** new_table) 278 struct acpi_table_header **new_table)
279{ 279{
280 280
281 if (!existing_table || !new_table) { 281 if (!existing_table || !new_table) {
@@ -311,8 +311,8 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
311 *****************************************************************************/ 311 *****************************************************************************/
312 312
313acpi_status 313acpi_status
314acpi_os_physical_table_override(struct acpi_table_header * existing_table, 314acpi_os_physical_table_override(struct acpi_table_header *existing_table,
315 acpi_physical_address * new_address, 315 acpi_physical_address *new_address,
316 u32 *new_table_length) 316 u32 *new_table_length)
317{ 317{
318 318
@@ -506,7 +506,7 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
506void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) 506void *acpi_os_map_memory(acpi_physical_address where, acpi_size length)
507{ 507{
508 508
509 return (ACPI_TO_POINTER((acpi_size) where)); 509 return (ACPI_TO_POINTER((acpi_size)where));
510} 510}
511 511
512/****************************************************************************** 512/******************************************************************************
@@ -603,9 +603,9 @@ void acpi_os_free(void *mem)
603 603
604acpi_status 604acpi_status
605acpi_os_create_semaphore(u32 max_units, 605acpi_os_create_semaphore(u32 max_units,
606 u32 initial_units, acpi_handle * out_handle) 606 u32 initial_units, acpi_handle *out_handle)
607{ 607{
608 *out_handle = (acpi_handle) 1; 608 *out_handle = (acpi_handle)1;
609 return (AE_OK); 609 return (AE_OK);
610} 610}
611 611
@@ -640,7 +640,7 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
640 640
641acpi_status 641acpi_status
642acpi_os_create_semaphore(u32 max_units, 642acpi_os_create_semaphore(u32 max_units,
643 u32 initial_units, acpi_handle * out_handle) 643 u32 initial_units, acpi_handle *out_handle)
644{ 644{
645 sem_t *sem; 645 sem_t *sem;
646 646
@@ -672,7 +672,7 @@ acpi_os_create_semaphore(u32 max_units,
672 } 672 }
673#endif 673#endif
674 674
675 *out_handle = (acpi_handle) sem; 675 *out_handle = (acpi_handle)sem;
676 return (AE_OK); 676 return (AE_OK);
677} 677}
678 678
@@ -1035,7 +1035,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
1035 *****************************************************************************/ 1035 *****************************************************************************/
1036 1036
1037acpi_status 1037acpi_status
1038acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, 1038acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
1039 u32 pci_register, u64 value, u32 width) 1039 u32 pci_register, u64 value, u32 width)
1040{ 1040{
1041 1041
diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c
index d070fccdba6d..a88ac45b7756 100644
--- a/tools/power/acpi/tools/acpidbg/acpidbg.c
+++ b/tools/power/acpi/tools/acpidbg/acpidbg.c
@@ -375,7 +375,7 @@ void usage(FILE *file, char *progname)
375 375
376int main(int argc, char **argv) 376int main(int argc, char **argv)
377{ 377{
378 int fd = 0; 378 int fd = -1;
379 int ch; 379 int ch;
380 int len; 380 int len;
381 int ret = EXIT_SUCCESS; 381 int ret = EXIT_SUCCESS;
@@ -430,7 +430,7 @@ int main(int argc, char **argv)
430 acpi_aml_loop(fd); 430 acpi_aml_loop(fd);
431 431
432exit: 432exit:
433 if (fd < 0) 433 if (fd >= 0)
434 close(fd); 434 close(fd);
435 if (acpi_aml_batch_cmd) 435 if (acpi_aml_batch_cmd)
436 free(acpi_aml_batch_cmd); 436 free(acpi_aml_batch_cmd);
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index 8d761576e91b..2942cdced2ad 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -31,6 +31,7 @@ TOOL_OBJS = \
31 osunixxf.o\ 31 osunixxf.o\
32 tbprint.o\ 32 tbprint.o\
33 tbxfroot.o\ 33 tbxfroot.o\
34 utascii.o\
34 utbuffer.o\ 35 utbuffer.o\
35 utdebug.o\ 36 utdebug.o\
36 utexcep.o\ 37 utexcep.o\
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index da44458d3b6c..fb8f1d9e3b1b 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -68,7 +68,7 @@ u8 ap_is_valid_header(struct acpi_table_header *table)
68 68
69 /* Make sure signature is all ASCII and a valid ACPI name */ 69 /* Make sure signature is all ASCII and a valid ACPI name */
70 70
71 if (!acpi_ut_valid_acpi_name(table->signature)) { 71 if (!acpi_ut_valid_nameseg(table->signature)) {
72 acpi_log_error("Table signature (0x%8.8X) is invalid\n", 72 acpi_log_error("Table signature (0x%8.8X) is invalid\n",
73 *(u32 *)table->signature); 73 *(u32 *)table->signature);
74 return (FALSE); 74 return (FALSE);
@@ -286,14 +286,15 @@ int ap_dump_table_by_address(char *ascii_address)
286 286
287 /* Convert argument to an integer physical address */ 287 /* Convert argument to an integer physical address */
288 288
289 status = acpi_ut_strtoul64(ascii_address, 0, &long_address); 289 status = acpi_ut_strtoul64(ascii_address, ACPI_ANY_BASE,
290 ACPI_MAX64_BYTE_WIDTH, &long_address);
290 if (ACPI_FAILURE(status)) { 291 if (ACPI_FAILURE(status)) {
291 acpi_log_error("%s: Could not convert to a physical address\n", 292 acpi_log_error("%s: Could not convert to a physical address\n",
292 ascii_address); 293 ascii_address);
293 return (-1); 294 return (-1);
294 } 295 }
295 296
296 address = (acpi_physical_address) long_address; 297 address = (acpi_physical_address)long_address;
297 status = acpi_os_get_table_by_address(address, &table); 298 status = acpi_os_get_table_by_address(address, &table);
298 if (ACPI_FAILURE(status)) { 299 if (ACPI_FAILURE(status)) {
299 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", 300 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n",
@@ -406,6 +407,12 @@ int ap_dump_table_from_file(char *pathname)
406 return (-1); 407 return (-1);
407 } 408 }
408 409
410 if (!acpi_ut_valid_nameseg(table->signature)) {
411 acpi_log_error
412 ("No valid ACPI signature was found in input file %s\n",
413 pathname);
414 }
415
409 /* File must be at least as long as the table length */ 416 /* File must be at least as long as the table length */
410 417
411 if (table->length > file_size) { 418 if (table->length > file_size) {
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index c3c09152fac6..7692e6b887e1 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -209,7 +209,8 @@ static int ap_do_options(int argc, char **argv)
209 case 'r': /* Dump tables from specified RSDP */ 209 case 'r': /* Dump tables from specified RSDP */
210 210
211 status = 211 status =
212 acpi_ut_strtoul64(acpi_gbl_optarg, 0, 212 acpi_ut_strtoul64(acpi_gbl_optarg, ACPI_ANY_BASE,
213 ACPI_MAX64_BYTE_WIDTH,
213 &gbl_rsdp_base); 214 &gbl_rsdp_base);
214 if (ACPI_FAILURE(status)) { 215 if (ACPI_FAILURE(status)) {
215 acpi_log_error 216 acpi_log_error
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 0adaf0c7c03a..8358863259c5 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -63,7 +63,7 @@ DESTDIR ?=
63# and _should_ modify the PACKAGE_BUGREPORT definition 63# and _should_ modify the PACKAGE_BUGREPORT definition
64 64
65VERSION= $(shell ./utils/version-gen.sh) 65VERSION= $(shell ./utils/version-gen.sh)
66LIB_MAJ= 0.0.0 66LIB_MAJ= 0.0.1
67LIB_MIN= 0 67LIB_MIN= 0
68 68
69PACKAGE = cpupower 69PACKAGE = cpupower
@@ -129,7 +129,7 @@ WARNINGS += -Wshadow
129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ 129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE 130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
131 131
132UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ 132UTIL_OBJS = utils/helpers/amd.o utils/helpers/msr.o \
133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \ 133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
134 utils/helpers/pci.o utils/helpers/bitmask.o \ 134 utils/helpers/pci.o utils/helpers/bitmask.o \
135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \ 135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
@@ -148,9 +148,9 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
148 utils/helpers/bitmask.h \ 148 utils/helpers/bitmask.h \
149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def 149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
150 150
151LIB_HEADERS = lib/cpufreq.h lib/sysfs.h 151LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
152LIB_SRC = lib/cpufreq.c lib/sysfs.c 152LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
153LIB_OBJS = lib/cpufreq.o lib/sysfs.o 153LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS)) 154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
155 155
156CFLAGS += -pipe 156CFLAGS += -pipe
@@ -280,6 +280,7 @@ install-lib:
280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ 280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/
281 $(INSTALL) -d $(DESTDIR)${includedir} 281 $(INSTALL) -d $(DESTDIR)${includedir}
282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h 282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
283 $(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
283 284
284install-tools: 285install-tools:
285 $(INSTALL) -d $(DESTDIR)${bindir} 286 $(INSTALL) -d $(DESTDIR)${bindir}
@@ -315,6 +316,7 @@ endif
315uninstall: 316uninstall:
316 - rm -f $(DESTDIR)${libdir}/libcpupower.* 317 - rm -f $(DESTDIR)${libdir}/libcpupower.*
317 - rm -f $(DESTDIR)${includedir}/cpufreq.h 318 - rm -f $(DESTDIR)${includedir}/cpufreq.h
319 - rm -f $(DESTDIR)${includedir}/cpuidle.h
318 - rm -f $(DESTDIR)${bindir}/utils/cpupower 320 - rm -f $(DESTDIR)${bindir}/utils/cpupower
319 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 321 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1
320 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 322 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
index d0f879b223fc..3e59f1aa3947 100644
--- a/tools/power/cpupower/bench/Makefile
+++ b/tools/power/cpupower/bench/Makefile
@@ -22,7 +22,7 @@ $(OUTPUT)%.o : %.c
22 22
23$(OUTPUT)cpufreq-bench: $(OBJS) 23$(OUTPUT)cpufreq-bench: $(OBJS)
24 $(ECHO) " CC " $@ 24 $(ECHO) " CC " $@
25 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) 25 $(QUIET) $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS)
26 26
27all: $(OUTPUT)cpufreq-bench 27all: $(OUTPUT)cpufreq-bench
28 28
diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH
index 8093ec738170..97727aed61cc 100644
--- a/tools/power/cpupower/bench/README-BENCH
+++ b/tools/power/cpupower/bench/README-BENCH
@@ -113,7 +113,7 @@ cpufreq-bench Command Usage
113-c, --cpu=<unsigned int> CPU Number to use, starting at 0 113-c, --cpu=<unsigned int> CPU Number to use, starting at 0
114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT 114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT
115-g, --governor=<governor> cpufreq governor to test 115-g, --governor=<governor> cpufreq governor to test
116-n, --cycles=<int> load/sleep cycles to get an avarage value to compare 116-n, --cycles=<int> load/sleep cycles to get an average value to compare
117-r, --rounds<int> load/sleep rounds 117-r, --rounds<int> load/sleep rounds
118-f, --file=<configfile> config file to use 118-f, --file=<configfile> config file to use
119-o, --output=<dir> output dir, must exist 119-o, --output=<dir> output dir, must exist
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
index 81b1c48607d9..429d51ab8031 100644
--- a/tools/power/cpupower/bench/benchmark.c
+++ b/tools/power/cpupower/bench/benchmark.c
@@ -130,7 +130,7 @@ void start_benchmark(struct config *config)
130 _round, load_time, sleep_time); 130 _round, load_time, sleep_time);
131 131
132 if (config->verbose) 132 if (config->verbose)
133 printf("avarage: %lius, rps:%li\n", 133 printf("average: %lius, rps:%li\n",
134 load_time / calculations, 134 load_time / calculations,
135 1000000 * calculations / load_time); 135 1000000 * calculations / load_time);
136 136
@@ -177,7 +177,7 @@ void start_benchmark(struct config *config)
177 177
178 progress_time += sleep_time + load_time; 178 progress_time += sleep_time + load_time;
179 179
180 /* compare the avarage sleep/load cycles */ 180 /* compare the average sleep/load cycles */
181 fprintf(config->output, "%li ", 181 fprintf(config->output, "%li ",
182 powersave_time / config->cycles); 182 powersave_time / config->cycles);
183 fprintf(config->output, "%.3f\n", 183 fprintf(config->output, "%.3f\n",
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
index f503fb53824e..9b65f052081f 100644
--- a/tools/power/cpupower/bench/parse.c
+++ b/tools/power/cpupower/bench/parse.c
@@ -65,7 +65,7 @@ FILE *prepare_output(const char *dirname)
65{ 65{
66 FILE *output = NULL; 66 FILE *output = NULL;
67 int len; 67 int len;
68 char *filename; 68 char *filename, *filename_tmp;
69 struct utsname sysdata; 69 struct utsname sysdata;
70 DIR *dir; 70 DIR *dir;
71 71
@@ -81,16 +81,22 @@ FILE *prepare_output(const char *dirname)
81 81
82 len = strlen(dirname) + 30; 82 len = strlen(dirname) + 30;
83 filename = malloc(sizeof(char) * len); 83 filename = malloc(sizeof(char) * len);
84 if (!filename) {
85 perror("malloc");
86 goto out_dir;
87 }
84 88
85 if (uname(&sysdata) == 0) { 89 if (uname(&sysdata) == 0) {
86 len += strlen(sysdata.nodename) + strlen(sysdata.release); 90 len += strlen(sysdata.nodename) + strlen(sysdata.release);
87 filename = realloc(filename, sizeof(char) * len); 91 filename_tmp = realloc(filename, sizeof(*filename) * len);
88 92
89 if (filename == NULL) { 93 if (filename_tmp == NULL) {
94 free(filename);
90 perror("realloc"); 95 perror("realloc");
91 return NULL; 96 goto out_dir;
92 } 97 }
93 98
99 filename = filename_tmp;
94 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", 100 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
95 dirname, sysdata.nodename, sysdata.release, time(NULL)); 101 dirname, sysdata.nodename, sysdata.release, time(NULL));
96 } else { 102 } else {
@@ -104,12 +110,16 @@ FILE *prepare_output(const char *dirname)
104 if (output == NULL) { 110 if (output == NULL) {
105 perror("fopen"); 111 perror("fopen");
106 fprintf(stderr, "error: unable to open logfile\n"); 112 fprintf(stderr, "error: unable to open logfile\n");
113 goto out;
107 } 114 }
108 115
109 fprintf(stdout, "Logfile: %s\n", filename); 116 fprintf(stdout, "Logfile: %s\n", filename);
110 117
111 free(filename);
112 fprintf(output, "#round load sleep performance powersave percentage\n"); 118 fprintf(output, "#round load sleep performance powersave percentage\n");
119out:
120 free(filename);
121out_dir:
122 closedir(dir);
113 return output; 123 return output;
114} 124}
115 125
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
index f01e3f4be84c..c25a74ae51ba 100644
--- a/tools/power/cpupower/bench/system.c
+++ b/tools/power/cpupower/bench/system.c
@@ -26,6 +26,7 @@
26#include <sched.h> 26#include <sched.h>
27 27
28#include <cpufreq.h> 28#include <cpufreq.h>
29#include <cpupower.h>
29 30
30#include "config.h" 31#include "config.h"
31#include "system.h" 32#include "system.h"
@@ -60,7 +61,7 @@ int set_cpufreq_governor(char *governor, unsigned int cpu)
60 61
61 dprintf("set %s as cpufreq governor\n", governor); 62 dprintf("set %s as cpufreq governor\n", governor);
62 63
63 if (cpufreq_cpu_exists(cpu) != 0) { 64 if (cpupower_is_cpu_online(cpu) != 0) {
64 perror("cpufreq_cpu_exists"); 65 perror("cpufreq_cpu_exists");
65 fprintf(stderr, "error: cpu %u does not exist\n", cpu); 66 fprintf(stderr, "error: cpu %u does not exist\n", cpu);
66 return -1; 67 return -1;
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
index d961101d1cea..1b993fe1ce23 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -9,28 +9,190 @@
9#include <errno.h> 9#include <errno.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
12 16
13#include "cpufreq.h" 17#include "cpufreq.h"
14#include "sysfs.h" 18#include "cpupower_intern.h"
15 19
16int cpufreq_cpu_exists(unsigned int cpu) 20/* CPUFREQ sysfs access **************************************************/
21
22/* helper function to read file from /sys into given buffer */
23/* fname is a relative path under "cpuX/cpufreq" dir */
24static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
25 char *buf, size_t buflen)
17{ 26{
18 return sysfs_cpu_exists(cpu); 27 char path[SYSFS_PATH_MAX];
28
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
30 cpu, fname);
31 return sysfs_read_file(path, buf, buflen);
19} 32}
20 33
34/* helper function to write a new value to a /sys file */
35/* fname is a relative path under "cpuX/cpufreq" dir */
36static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
37 const char *fname,
38 const char *value, size_t len)
39{
40 char path[SYSFS_PATH_MAX];
41 int fd;
42 ssize_t numwrite;
43
44 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
45 cpu, fname);
46
47 fd = open(path, O_WRONLY);
48 if (fd == -1)
49 return 0;
50
51 numwrite = write(fd, value, len);
52 if (numwrite < 1) {
53 close(fd);
54 return 0;
55 }
56
57 close(fd);
58
59 return (unsigned int) numwrite;
60}
61
62/* read access to files which contain one numeric value */
63
64enum cpufreq_value {
65 CPUINFO_CUR_FREQ,
66 CPUINFO_MIN_FREQ,
67 CPUINFO_MAX_FREQ,
68 CPUINFO_LATENCY,
69 SCALING_CUR_FREQ,
70 SCALING_MIN_FREQ,
71 SCALING_MAX_FREQ,
72 STATS_NUM_TRANSITIONS,
73 MAX_CPUFREQ_VALUE_READ_FILES
74};
75
76static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
77 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
78 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
79 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
80 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
81 [SCALING_CUR_FREQ] = "scaling_cur_freq",
82 [SCALING_MIN_FREQ] = "scaling_min_freq",
83 [SCALING_MAX_FREQ] = "scaling_max_freq",
84 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
85};
86
87
88static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
89 enum cpufreq_value which)
90{
91 unsigned long value;
92 unsigned int len;
93 char linebuf[MAX_LINE_LEN];
94 char *endp;
95
96 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
97 return 0;
98
99 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
100 linebuf, sizeof(linebuf));
101
102 if (len == 0)
103 return 0;
104
105 value = strtoul(linebuf, &endp, 0);
106
107 if (endp == linebuf || errno == ERANGE)
108 return 0;
109
110 return value;
111}
112
113/* read access to files which contain one string */
114
115enum cpufreq_string {
116 SCALING_DRIVER,
117 SCALING_GOVERNOR,
118 MAX_CPUFREQ_STRING_FILES
119};
120
121static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
122 [SCALING_DRIVER] = "scaling_driver",
123 [SCALING_GOVERNOR] = "scaling_governor",
124};
125
126
127static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
128 enum cpufreq_string which)
129{
130 char linebuf[MAX_LINE_LEN];
131 char *result;
132 unsigned int len;
133
134 if (which >= MAX_CPUFREQ_STRING_FILES)
135 return NULL;
136
137 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
138 linebuf, sizeof(linebuf));
139 if (len == 0)
140 return NULL;
141
142 result = strdup(linebuf);
143 if (result == NULL)
144 return NULL;
145
146 if (result[strlen(result) - 1] == '\n')
147 result[strlen(result) - 1] = '\0';
148
149 return result;
150}
151
152/* write access */
153
154enum cpufreq_write {
155 WRITE_SCALING_MIN_FREQ,
156 WRITE_SCALING_MAX_FREQ,
157 WRITE_SCALING_GOVERNOR,
158 WRITE_SCALING_SET_SPEED,
159 MAX_CPUFREQ_WRITE_FILES
160};
161
162static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
163 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
164 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
165 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
166 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
167};
168
169static int sysfs_cpufreq_write_one_value(unsigned int cpu,
170 enum cpufreq_write which,
171 const char *new_value, size_t len)
172{
173 if (which >= MAX_CPUFREQ_WRITE_FILES)
174 return 0;
175
176 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
177 new_value, len) != len)
178 return -ENODEV;
179
180 return 0;
181};
182
21unsigned long cpufreq_get_freq_kernel(unsigned int cpu) 183unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
22{ 184{
23 return sysfs_get_freq_kernel(cpu); 185 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
24} 186}
25 187
26unsigned long cpufreq_get_freq_hardware(unsigned int cpu) 188unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
27{ 189{
28 return sysfs_get_freq_hardware(cpu); 190 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
29} 191}
30 192
31unsigned long cpufreq_get_transition_latency(unsigned int cpu) 193unsigned long cpufreq_get_transition_latency(unsigned int cpu)
32{ 194{
33 return sysfs_get_freq_transition_latency(cpu); 195 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
34} 196}
35 197
36int cpufreq_get_hardware_limits(unsigned int cpu, 198int cpufreq_get_hardware_limits(unsigned int cpu,
@@ -39,12 +201,21 @@ int cpufreq_get_hardware_limits(unsigned int cpu,
39{ 201{
40 if ((!min) || (!max)) 202 if ((!min) || (!max))
41 return -EINVAL; 203 return -EINVAL;
42 return sysfs_get_freq_hardware_limits(cpu, min, max); 204
205 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
206 if (!*min)
207 return -ENODEV;
208
209 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
210 if (!*max)
211 return -ENODEV;
212
213 return 0;
43} 214}
44 215
45char *cpufreq_get_driver(unsigned int cpu) 216char *cpufreq_get_driver(unsigned int cpu)
46{ 217{
47 return sysfs_get_freq_driver(cpu); 218 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
48} 219}
49 220
50void cpufreq_put_driver(char *ptr) 221void cpufreq_put_driver(char *ptr)
@@ -56,7 +227,26 @@ void cpufreq_put_driver(char *ptr)
56 227
57struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu) 228struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
58{ 229{
59 return sysfs_get_freq_policy(cpu); 230 struct cpufreq_policy *policy;
231
232 policy = malloc(sizeof(struct cpufreq_policy));
233 if (!policy)
234 return NULL;
235
236 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
237 if (!policy->governor) {
238 free(policy);
239 return NULL;
240 }
241 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
242 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
243 if ((!policy->min) || (!policy->max)) {
244 free(policy->governor);
245 free(policy);
246 return NULL;
247 }
248
249 return policy;
60} 250}
61 251
62void cpufreq_put_policy(struct cpufreq_policy *policy) 252void cpufreq_put_policy(struct cpufreq_policy *policy)
@@ -72,7 +262,57 @@ void cpufreq_put_policy(struct cpufreq_policy *policy)
72struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned 262struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
73 int cpu) 263 int cpu)
74{ 264{
75 return sysfs_get_freq_available_governors(cpu); 265 struct cpufreq_available_governors *first = NULL;
266 struct cpufreq_available_governors *current = NULL;
267 char linebuf[MAX_LINE_LEN];
268 unsigned int pos, i;
269 unsigned int len;
270
271 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
272 linebuf, sizeof(linebuf));
273 if (len == 0)
274 return NULL;
275
276 pos = 0;
277 for (i = 0; i < len; i++) {
278 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
279 if (i - pos < 2)
280 continue;
281 if (current) {
282 current->next = malloc(sizeof(*current));
283 if (!current->next)
284 goto error_out;
285 current = current->next;
286 } else {
287 first = malloc(sizeof(*first));
288 if (!first)
289 goto error_out;
290 current = first;
291 }
292 current->first = first;
293 current->next = NULL;
294
295 current->governor = malloc(i - pos + 1);
296 if (!current->governor)
297 goto error_out;
298
299 memcpy(current->governor, linebuf + pos, i - pos);
300 current->governor[i - pos] = '\0';
301 pos = i + 1;
302 }
303 }
304
305 return first;
306
307 error_out:
308 while (first) {
309 current = first->next;
310 if (first->governor)
311 free(first->governor);
312 free(first);
313 first = current;
314 }
315 return NULL;
76} 316}
77 317
78void cpufreq_put_available_governors(struct cpufreq_available_governors *any) 318void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
@@ -96,7 +336,57 @@ void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
96struct cpufreq_available_frequencies 336struct cpufreq_available_frequencies
97*cpufreq_get_available_frequencies(unsigned int cpu) 337*cpufreq_get_available_frequencies(unsigned int cpu)
98{ 338{
99 return sysfs_get_available_frequencies(cpu); 339 struct cpufreq_available_frequencies *first = NULL;
340 struct cpufreq_available_frequencies *current = NULL;
341 char one_value[SYSFS_PATH_MAX];
342 char linebuf[MAX_LINE_LEN];
343 unsigned int pos, i;
344 unsigned int len;
345
346 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
347 linebuf, sizeof(linebuf));
348 if (len == 0)
349 return NULL;
350
351 pos = 0;
352 for (i = 0; i < len; i++) {
353 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
354 if (i - pos < 2)
355 continue;
356 if (i - pos >= SYSFS_PATH_MAX)
357 goto error_out;
358 if (current) {
359 current->next = malloc(sizeof(*current));
360 if (!current->next)
361 goto error_out;
362 current = current->next;
363 } else {
364 first = malloc(sizeof(*first));
365 if (!first)
366 goto error_out;
367 current = first;
368 }
369 current->first = first;
370 current->next = NULL;
371
372 memcpy(one_value, linebuf + pos, i - pos);
373 one_value[i - pos] = '\0';
374 if (sscanf(one_value, "%lu", &current->frequency) != 1)
375 goto error_out;
376
377 pos = i + 1;
378 }
379 }
380
381 return first;
382
383 error_out:
384 while (first) {
385 current = first->next;
386 free(first);
387 first = current;
388 }
389 return NULL;
100} 390}
101 391
102void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies 392void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
@@ -114,10 +404,65 @@ void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
114 } 404 }
115} 405}
116 406
407static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
408 const char *file)
409{
410 struct cpufreq_affected_cpus *first = NULL;
411 struct cpufreq_affected_cpus *current = NULL;
412 char one_value[SYSFS_PATH_MAX];
413 char linebuf[MAX_LINE_LEN];
414 unsigned int pos, i;
415 unsigned int len;
416
417 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
418 if (len == 0)
419 return NULL;
420
421 pos = 0;
422 for (i = 0; i < len; i++) {
423 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
424 if (i - pos < 1)
425 continue;
426 if (i - pos >= SYSFS_PATH_MAX)
427 goto error_out;
428 if (current) {
429 current->next = malloc(sizeof(*current));
430 if (!current->next)
431 goto error_out;
432 current = current->next;
433 } else {
434 first = malloc(sizeof(*first));
435 if (!first)
436 goto error_out;
437 current = first;
438 }
439 current->first = first;
440 current->next = NULL;
441
442 memcpy(one_value, linebuf + pos, i - pos);
443 one_value[i - pos] = '\0';
444
445 if (sscanf(one_value, "%u", &current->cpu) != 1)
446 goto error_out;
447
448 pos = i + 1;
449 }
450 }
451
452 return first;
453
454 error_out:
455 while (first) {
456 current = first->next;
457 free(first);
458 first = current;
459 }
460 return NULL;
461}
117 462
118struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu) 463struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
119{ 464{
120 return sysfs_get_freq_affected_cpus(cpu); 465 return sysfs_get_cpu_list(cpu, "affected_cpus");
121} 466}
122 467
123void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) 468void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
@@ -138,7 +483,7 @@ void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
138 483
139struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu) 484struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
140{ 485{
141 return sysfs_get_freq_related_cpus(cpu); 486 return sysfs_get_cpu_list(cpu, "related_cpus");
142} 487}
143 488
144void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) 489void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
@@ -146,45 +491,208 @@ void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
146 cpufreq_put_affected_cpus(any); 491 cpufreq_put_affected_cpus(any);
147} 492}
148 493
494static int verify_gov(char *new_gov, char *passed_gov)
495{
496 unsigned int i, j = 0;
497
498 if (!passed_gov || (strlen(passed_gov) > 19))
499 return -EINVAL;
500
501 strncpy(new_gov, passed_gov, 20);
502 for (i = 0; i < 20; i++) {
503 if (j) {
504 new_gov[i] = '\0';
505 continue;
506 }
507 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
508 continue;
509
510 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
511 continue;
512
513 if (new_gov[i] == '-')
514 continue;
515
516 if (new_gov[i] == '_')
517 continue;
518
519 if (new_gov[i] == '\0') {
520 j = 1;
521 continue;
522 }
523 return -EINVAL;
524 }
525 new_gov[19] = '\0';
526 return 0;
527}
149 528
150int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) 529int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
151{ 530{
531 char min[SYSFS_PATH_MAX];
532 char max[SYSFS_PATH_MAX];
533 char gov[SYSFS_PATH_MAX];
534 int ret;
535 unsigned long old_min;
536 int write_max_first;
537
152 if (!policy || !(policy->governor)) 538 if (!policy || !(policy->governor))
153 return -EINVAL; 539 return -EINVAL;
154 540
155 return sysfs_set_freq_policy(cpu, policy); 541 if (policy->max < policy->min)
542 return -EINVAL;
543
544 if (verify_gov(gov, policy->governor))
545 return -EINVAL;
546
547 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
548 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
549
550 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
551 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
552
553 if (write_max_first) {
554 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
555 max, strlen(max));
556 if (ret)
557 return ret;
558 }
559
560 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
561 strlen(min));
562 if (ret)
563 return ret;
564
565 if (!write_max_first) {
566 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
567 max, strlen(max));
568 if (ret)
569 return ret;
570 }
571
572 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
573 gov, strlen(gov));
156} 574}
157 575
158 576
159int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) 577int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
160{ 578{
161 return sysfs_modify_freq_policy_min(cpu, min_freq); 579 char value[SYSFS_PATH_MAX];
580
581 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
582
583 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
584 value, strlen(value));
162} 585}
163 586
164 587
165int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) 588int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
166{ 589{
167 return sysfs_modify_freq_policy_max(cpu, max_freq); 590 char value[SYSFS_PATH_MAX];
168} 591
592 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
169 593
594 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
595 value, strlen(value));
596}
170 597
171int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) 598int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
172{ 599{
600 char new_gov[SYSFS_PATH_MAX];
601
173 if ((!governor) || (strlen(governor) > 19)) 602 if ((!governor) || (strlen(governor) > 19))
174 return -EINVAL; 603 return -EINVAL;
175 604
176 return sysfs_modify_freq_policy_governor(cpu, governor); 605 if (verify_gov(new_gov, governor))
606 return -EINVAL;
607
608 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
609 new_gov, strlen(new_gov));
177} 610}
178 611
179int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) 612int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
180{ 613{
181 return sysfs_set_frequency(cpu, target_frequency); 614 struct cpufreq_policy *pol = cpufreq_get_policy(cpu);
615 char userspace_gov[] = "userspace";
616 char freq[SYSFS_PATH_MAX];
617 int ret;
618
619 if (!pol)
620 return -ENODEV;
621
622 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
623 ret = cpufreq_modify_policy_governor(cpu, userspace_gov);
624 if (ret) {
625 cpufreq_put_policy(pol);
626 return ret;
627 }
628 }
629
630 cpufreq_put_policy(pol);
631
632 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
633
634 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
635 freq, strlen(freq));
182} 636}
183 637
184struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 638struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
185 unsigned long long *total_time) 639 unsigned long long *total_time)
186{ 640{
187 return sysfs_get_freq_stats(cpu, total_time); 641 struct cpufreq_stats *first = NULL;
642 struct cpufreq_stats *current = NULL;
643 char one_value[SYSFS_PATH_MAX];
644 char linebuf[MAX_LINE_LEN];
645 unsigned int pos, i;
646 unsigned int len;
647
648 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
649 linebuf, sizeof(linebuf));
650 if (len == 0)
651 return NULL;
652
653 *total_time = 0;
654 pos = 0;
655 for (i = 0; i < len; i++) {
656 if (i == strlen(linebuf) || linebuf[i] == '\n') {
657 if (i - pos < 2)
658 continue;
659 if ((i - pos) >= SYSFS_PATH_MAX)
660 goto error_out;
661 if (current) {
662 current->next = malloc(sizeof(*current));
663 if (!current->next)
664 goto error_out;
665 current = current->next;
666 } else {
667 first = malloc(sizeof(*first));
668 if (!first)
669 goto error_out;
670 current = first;
671 }
672 current->first = first;
673 current->next = NULL;
674
675 memcpy(one_value, linebuf + pos, i - pos);
676 one_value[i - pos] = '\0';
677 if (sscanf(one_value, "%lu %llu",
678 &current->frequency,
679 &current->time_in_state) != 2)
680 goto error_out;
681
682 *total_time = *total_time + current->time_in_state;
683 pos = i + 1;
684 }
685 }
686
687 return first;
688
689 error_out:
690 while (first) {
691 current = first->next;
692 free(first);
693 first = current;
694 }
695 return NULL;
188} 696}
189 697
190void cpufreq_put_stats(struct cpufreq_stats *any) 698void cpufreq_put_stats(struct cpufreq_stats *any)
@@ -204,5 +712,5 @@ void cpufreq_put_stats(struct cpufreq_stats *any)
204 712
205unsigned long cpufreq_get_transitions(unsigned int cpu) 713unsigned long cpufreq_get_transitions(unsigned int cpu)
206{ 714{
207 return sysfs_get_freq_transitions(cpu); 715 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
208} 716}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
index 3aae8e7a0839..3b005c39f068 100644
--- a/tools/power/cpupower/lib/cpufreq.h
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -17,8 +17,8 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#ifndef _CPUFREQ_H 20#ifndef __CPUPOWER_CPUFREQ_H__
21#define _CPUFREQ_H 1 21#define __CPUPOWER_CPUFREQ_H__
22 22
23struct cpufreq_policy { 23struct cpufreq_policy {
24 unsigned long min; 24 unsigned long min;
@@ -58,13 +58,6 @@ struct cpufreq_stats {
58extern "C" { 58extern "C" {
59#endif 59#endif
60 60
61/*
62 * returns 0 if the specified CPU is present (it doesn't say
63 * whether it is online!), and an error value if not.
64 */
65
66extern int cpufreq_cpu_exists(unsigned int cpu);
67
68/* determine current CPU frequency 61/* determine current CPU frequency
69 * - _kernel variant means kernel's opinion of CPU frequency 62 * - _kernel variant means kernel's opinion of CPU frequency
70 * - _hardware variant means actual hardware CPU frequency, 63 * - _hardware variant means actual hardware CPU frequency,
@@ -73,9 +66,9 @@ extern int cpufreq_cpu_exists(unsigned int cpu);
73 * returns 0 on failure, else frequency in kHz. 66 * returns 0 on failure, else frequency in kHz.
74 */ 67 */
75 68
76extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu); 69unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
77 70
78extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu); 71unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
79 72
80#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu); 73#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
81 74
@@ -84,7 +77,7 @@ extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
84 * 77 *
85 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds 78 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
86 */ 79 */
87extern unsigned long cpufreq_get_transition_latency(unsigned int cpu); 80unsigned long cpufreq_get_transition_latency(unsigned int cpu);
88 81
89 82
90/* determine hardware CPU frequency limits 83/* determine hardware CPU frequency limits
@@ -93,7 +86,7 @@ extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
93 * considerations by cpufreq policy notifiers in the kernel. 86 * considerations by cpufreq policy notifiers in the kernel.
94 */ 87 */
95 88
96extern int cpufreq_get_hardware_limits(unsigned int cpu, 89int cpufreq_get_hardware_limits(unsigned int cpu,
97 unsigned long *min, 90 unsigned long *min,
98 unsigned long *max); 91 unsigned long *max);
99 92
@@ -104,9 +97,9 @@ extern int cpufreq_get_hardware_limits(unsigned int cpu,
104 * to avoid memory leakage, please. 97 * to avoid memory leakage, please.
105 */ 98 */
106 99
107extern char *cpufreq_get_driver(unsigned int cpu); 100char *cpufreq_get_driver(unsigned int cpu);
108 101
109extern void cpufreq_put_driver(char *ptr); 102void cpufreq_put_driver(char *ptr);
110 103
111 104
112/* determine CPUfreq policy currently used 105/* determine CPUfreq policy currently used
@@ -116,9 +109,9 @@ extern void cpufreq_put_driver(char *ptr);
116 */ 109 */
117 110
118 111
119extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu); 112struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
120 113
121extern void cpufreq_put_policy(struct cpufreq_policy *policy); 114void cpufreq_put_policy(struct cpufreq_policy *policy);
122 115
123 116
124/* determine CPUfreq governors currently available 117/* determine CPUfreq governors currently available
@@ -129,10 +122,10 @@ extern void cpufreq_put_policy(struct cpufreq_policy *policy);
129 */ 122 */
130 123
131 124
132extern struct cpufreq_available_governors 125struct cpufreq_available_governors
133*cpufreq_get_available_governors(unsigned int cpu); 126*cpufreq_get_available_governors(unsigned int cpu);
134 127
135extern void cpufreq_put_available_governors( 128void cpufreq_put_available_governors(
136 struct cpufreq_available_governors *first); 129 struct cpufreq_available_governors *first);
137 130
138 131
@@ -143,10 +136,10 @@ extern void cpufreq_put_available_governors(
143 * cpufreq_put_available_frequencies after use. 136 * cpufreq_put_available_frequencies after use.
144 */ 137 */
145 138
146extern struct cpufreq_available_frequencies 139struct cpufreq_available_frequencies
147*cpufreq_get_available_frequencies(unsigned int cpu); 140*cpufreq_get_available_frequencies(unsigned int cpu);
148 141
149extern void cpufreq_put_available_frequencies( 142void cpufreq_put_available_frequencies(
150 struct cpufreq_available_frequencies *first); 143 struct cpufreq_available_frequencies *first);
151 144
152 145
@@ -156,10 +149,10 @@ extern void cpufreq_put_available_frequencies(
156 * to avoid memory leakage, please. 149 * to avoid memory leakage, please.
157 */ 150 */
158 151
159extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned 152struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
160 int cpu); 153 int cpu);
161 154
162extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first); 155void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
163 156
164 157
165/* determine related CPUs 158/* determine related CPUs
@@ -168,10 +161,10 @@ extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
168 * to avoid memory leakage, please. 161 * to avoid memory leakage, please.
169 */ 162 */
170 163
171extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned 164struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
172 int cpu); 165 int cpu);
173 166
174extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); 167void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
175 168
176 169
177/* determine stats for cpufreq subsystem 170/* determine stats for cpufreq subsystem
@@ -179,12 +172,12 @@ extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
179 * This is not available in all kernel versions or configurations. 172 * This is not available in all kernel versions or configurations.
180 */ 173 */
181 174
182extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 175struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
183 unsigned long long *total_time); 176 unsigned long long *total_time);
184 177
185extern void cpufreq_put_stats(struct cpufreq_stats *stats); 178void cpufreq_put_stats(struct cpufreq_stats *stats);
186 179
187extern unsigned long cpufreq_get_transitions(unsigned int cpu); 180unsigned long cpufreq_get_transitions(unsigned int cpu);
188 181
189 182
190/* set new cpufreq policy 183/* set new cpufreq policy
@@ -193,7 +186,7 @@ extern unsigned long cpufreq_get_transitions(unsigned int cpu);
193 * but results may differ depending e.g. on governors being available. 186 * but results may differ depending e.g. on governors being available.
194 */ 187 */
195 188
196extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); 189int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
197 190
198 191
199/* modify a policy by only changing min/max freq or governor 192/* modify a policy by only changing min/max freq or governor
@@ -201,9 +194,9 @@ extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
201 * Does not check whether result is what was intended. 194 * Does not check whether result is what was intended.
202 */ 195 */
203 196
204extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); 197int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
205extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq); 198int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
206extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor); 199int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
207 200
208 201
209/* set a specific frequency 202/* set a specific frequency
@@ -213,7 +206,7 @@ extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
213 * occurs. Also does not work on ->range() cpufreq drivers. 206 * occurs. Also does not work on ->range() cpufreq drivers.
214 */ 207 */
215 208
216extern int cpufreq_set_frequency(unsigned int cpu, 209int cpufreq_set_frequency(unsigned int cpu,
217 unsigned long target_frequency); 210 unsigned long target_frequency);
218 211
219#ifdef __cplusplus 212#ifdef __cplusplus
diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/cpuidle.c
new file mode 100644
index 000000000000..9bd4c7655fdb
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.c
@@ -0,0 +1,380 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpuidle.h"
18#include "cpupower_intern.h"
19
20/*
21 * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
22 * exists.
23 * For example the functionality to disable c-states was introduced in later
24 * kernel versions, this function can be used to explicitly check for this
25 * feature.
26 *
27 * returns 1 if the file exists, 0 otherwise.
28 */
29static
30unsigned int cpuidle_state_file_exists(unsigned int cpu,
31 unsigned int idlestate,
32 const char *fname)
33{
34 char path[SYSFS_PATH_MAX];
35 struct stat statbuf;
36
37
38 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
39 cpu, idlestate, fname);
40 if (stat(path, &statbuf) != 0)
41 return 0;
42 return 1;
43}
44
45/*
46 * helper function to read file from /sys into given buffer
47 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
48 * cstates starting with 0, C0 is not counted as cstate.
49 * This means if you want C1 info, pass 0 as idlestate param
50 */
51static
52unsigned int cpuidle_state_read_file(unsigned int cpu,
53 unsigned int idlestate,
54 const char *fname, char *buf,
55 size_t buflen)
56{
57 char path[SYSFS_PATH_MAX];
58 int fd;
59 ssize_t numread;
60
61 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
62 cpu, idlestate, fname);
63
64 fd = open(path, O_RDONLY);
65 if (fd == -1)
66 return 0;
67
68 numread = read(fd, buf, buflen - 1);
69 if (numread < 1) {
70 close(fd);
71 return 0;
72 }
73
74 buf[numread] = '\0';
75 close(fd);
76
77 return (unsigned int) numread;
78}
79
80/*
81 * helper function to write a new value to a /sys file
82 * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir
83 *
84 * Returns the number of bytes written or 0 on error
85 */
86static
87unsigned int cpuidle_state_write_file(unsigned int cpu,
88 unsigned int idlestate,
89 const char *fname,
90 const char *value, size_t len)
91{
92 char path[SYSFS_PATH_MAX];
93 int fd;
94 ssize_t numwrite;
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
97 cpu, idlestate, fname);
98
99 fd = open(path, O_WRONLY);
100 if (fd == -1)
101 return 0;
102
103 numwrite = write(fd, value, len);
104 if (numwrite < 1) {
105 close(fd);
106 return 0;
107 }
108
109 close(fd);
110
111 return (unsigned int) numwrite;
112}
113
114/* read access to files which contain one numeric value */
115
116enum idlestate_value {
117 IDLESTATE_USAGE,
118 IDLESTATE_POWER,
119 IDLESTATE_LATENCY,
120 IDLESTATE_TIME,
121 IDLESTATE_DISABLE,
122 MAX_IDLESTATE_VALUE_FILES
123};
124
125static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
126 [IDLESTATE_USAGE] = "usage",
127 [IDLESTATE_POWER] = "power",
128 [IDLESTATE_LATENCY] = "latency",
129 [IDLESTATE_TIME] = "time",
130 [IDLESTATE_DISABLE] = "disable",
131};
132
133static
134unsigned long long cpuidle_state_get_one_value(unsigned int cpu,
135 unsigned int idlestate,
136 enum idlestate_value which)
137{
138 unsigned long long value;
139 unsigned int len;
140 char linebuf[MAX_LINE_LEN];
141 char *endp;
142
143 if (which >= MAX_IDLESTATE_VALUE_FILES)
144 return 0;
145
146 len = cpuidle_state_read_file(cpu, idlestate,
147 idlestate_value_files[which],
148 linebuf, sizeof(linebuf));
149 if (len == 0)
150 return 0;
151
152 value = strtoull(linebuf, &endp, 0);
153
154 if (endp == linebuf || errno == ERANGE)
155 return 0;
156
157 return value;
158}
159
160/* read access to files which contain one string */
161
162enum idlestate_string {
163 IDLESTATE_DESC,
164 IDLESTATE_NAME,
165 MAX_IDLESTATE_STRING_FILES
166};
167
168static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
169 [IDLESTATE_DESC] = "desc",
170 [IDLESTATE_NAME] = "name",
171};
172
173
174static char *cpuidle_state_get_one_string(unsigned int cpu,
175 unsigned int idlestate,
176 enum idlestate_string which)
177{
178 char linebuf[MAX_LINE_LEN];
179 char *result;
180 unsigned int len;
181
182 if (which >= MAX_IDLESTATE_STRING_FILES)
183 return NULL;
184
185 len = cpuidle_state_read_file(cpu, idlestate,
186 idlestate_string_files[which],
187 linebuf, sizeof(linebuf));
188 if (len == 0)
189 return NULL;
190
191 result = strdup(linebuf);
192 if (result == NULL)
193 return NULL;
194
195 if (result[strlen(result) - 1] == '\n')
196 result[strlen(result) - 1] = '\0';
197
198 return result;
199}
200
201/*
202 * Returns:
203 * 1 if disabled
204 * 0 if enabled
205 * -1 if idlestate is not available
206 * -2 if disabling is not supported by the kernel
207 */
208int cpuidle_is_state_disabled(unsigned int cpu,
209 unsigned int idlestate)
210{
211 if (cpuidle_state_count(cpu) <= idlestate)
212 return -1;
213
214 if (!cpuidle_state_file_exists(cpu, idlestate,
215 idlestate_value_files[IDLESTATE_DISABLE]))
216 return -2;
217 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
218}
219
220/*
221 * Pass 1 as last argument to disable or 0 to enable the state
222 * Returns:
223 * 0 on success
224 * negative values on error, for example:
225 * -1 if idlestate is not available
226 * -2 if disabling is not supported by the kernel
227 * -3 No write access to disable/enable C-states
228 */
229int cpuidle_state_disable(unsigned int cpu,
230 unsigned int idlestate,
231 unsigned int disable)
232{
233 char value[SYSFS_PATH_MAX];
234 int bytes_written;
235
236 if (cpuidle_state_count(cpu) <= idlestate)
237 return -1;
238
239 if (!cpuidle_state_file_exists(cpu, idlestate,
240 idlestate_value_files[IDLESTATE_DISABLE]))
241 return -2;
242
243 snprintf(value, SYSFS_PATH_MAX, "%u", disable);
244
245 bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable",
246 value, sizeof(disable));
247 if (bytes_written)
248 return 0;
249 return -3;
250}
251
252unsigned long cpuidle_state_latency(unsigned int cpu,
253 unsigned int idlestate)
254{
255 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
256}
257
258unsigned long cpuidle_state_usage(unsigned int cpu,
259 unsigned int idlestate)
260{
261 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
262}
263
264unsigned long long cpuidle_state_time(unsigned int cpu,
265 unsigned int idlestate)
266{
267 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_TIME);
268}
269
270char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate)
271{
272 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_NAME);
273}
274
275char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate)
276{
277 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_DESC);
278}
279
280/*
281 * Returns number of supported C-states of CPU core cpu
282 * Negativ in error case
283 * Zero if cpuidle does not export any C-states
284 */
285unsigned int cpuidle_state_count(unsigned int cpu)
286{
287 char file[SYSFS_PATH_MAX];
288 struct stat statbuf;
289 int idlestates = 1;
290
291
292 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
293 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
294 return 0;
295
296 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
297 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
298 return 0;
299
300 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
301 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
302 "cpu%u/cpuidle/state%d", cpu, idlestates);
303 idlestates++;
304 }
305 idlestates--;
306 return idlestates;
307}
308
309/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
310
311/*
312 * helper function to read file from /sys into given buffer
313 * fname is a relative path under "cpu/cpuidle/" dir
314 */
315static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
316 size_t buflen)
317{
318 char path[SYSFS_PATH_MAX];
319
320 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
321
322 return sysfs_read_file(path, buf, buflen);
323}
324
325
326
327/* read access to files which contain one string */
328
329enum cpuidle_string {
330 CPUIDLE_GOVERNOR,
331 CPUIDLE_GOVERNOR_RO,
332 CPUIDLE_DRIVER,
333 MAX_CPUIDLE_STRING_FILES
334};
335
336static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
337 [CPUIDLE_GOVERNOR] = "current_governor",
338 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
339 [CPUIDLE_DRIVER] = "current_driver",
340};
341
342
343static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
344{
345 char linebuf[MAX_LINE_LEN];
346 char *result;
347 unsigned int len;
348
349 if (which >= MAX_CPUIDLE_STRING_FILES)
350 return NULL;
351
352 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
353 linebuf, sizeof(linebuf));
354 if (len == 0)
355 return NULL;
356
357 result = strdup(linebuf);
358 if (result == NULL)
359 return NULL;
360
361 if (result[strlen(result) - 1] == '\n')
362 result[strlen(result) - 1] = '\0';
363
364 return result;
365}
366
367char *cpuidle_get_governor(void)
368{
369 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
370 if (!tmp)
371 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
372 else
373 return tmp;
374}
375
376char *cpuidle_get_driver(void)
377{
378 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
379}
380/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
diff --git a/tools/power/cpupower/lib/cpuidle.h b/tools/power/cpupower/lib/cpuidle.h
new file mode 100644
index 000000000000..04eb3cfa6e42
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.h
@@ -0,0 +1,23 @@
1#ifndef __CPUPOWER_CPUIDLE_H__
2#define __CPUPOWER_CPUIDLE_H__
3
4int cpuidle_is_state_disabled(unsigned int cpu,
5 unsigned int idlestate);
6int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate,
7 unsigned int disable);
8unsigned long cpuidle_state_latency(unsigned int cpu,
9 unsigned int idlestate);
10unsigned long cpuidle_state_usage(unsigned int cpu,
11 unsigned int idlestate);
12unsigned long long cpuidle_state_time(unsigned int cpu,
13 unsigned int idlestate);
14char *cpuidle_state_name(unsigned int cpu,
15 unsigned int idlestate);
16char *cpuidle_state_desc(unsigned int cpu,
17 unsigned int idlestate);
18unsigned int cpuidle_state_count(unsigned int cpu);
19
20char *cpuidle_get_governor(void);
21char *cpuidle_get_driver(void);
22
23#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c
new file mode 100644
index 000000000000..9c395ec924de
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.c
@@ -0,0 +1,192 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <errno.h>
13#include <stdlib.h>
14
15#include "cpupower.h"
16#include "cpupower_intern.h"
17
18unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
19{
20 int fd;
21 ssize_t numread;
22
23 fd = open(path, O_RDONLY);
24 if (fd == -1)
25 return 0;
26
27 numread = read(fd, buf, buflen - 1);
28 if (numread < 1) {
29 close(fd);
30 return 0;
31 }
32
33 buf[numread] = '\0';
34 close(fd);
35
36 return (unsigned int) numread;
37}
38
39/*
40 * Detect whether a CPU is online
41 *
42 * Returns:
43 * 1 -> if CPU is online
44 * 0 -> if CPU is offline
45 * negative errno values in error case
46 */
47int cpupower_is_cpu_online(unsigned int cpu)
48{
49 char path[SYSFS_PATH_MAX];
50 int fd;
51 ssize_t numread;
52 unsigned long long value;
53 char linebuf[MAX_LINE_LEN];
54 char *endp;
55 struct stat statbuf;
56
57 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
58
59 if (stat(path, &statbuf) != 0)
60 return 0;
61
62 /*
63 * kernel without CONFIG_HOTPLUG_CPU
64 * -> cpuX directory exists, but not cpuX/online file
65 */
66 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
67 if (stat(path, &statbuf) != 0)
68 return 1;
69
70 fd = open(path, O_RDONLY);
71 if (fd == -1)
72 return -errno;
73
74 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
75 if (numread < 1) {
76 close(fd);
77 return -EIO;
78 }
79 linebuf[numread] = '\0';
80 close(fd);
81
82 value = strtoull(linebuf, &endp, 0);
83 if (value > 1)
84 return -EINVAL;
85
86 return value;
87}
88
89/* returns -1 on failure, 0 on success */
90static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
91{
92 char linebuf[MAX_LINE_LEN];
93 char *endp;
94 char path[SYSFS_PATH_MAX];
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
97 cpu, fname);
98 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
99 return -1;
100 *result = strtol(linebuf, &endp, 0);
101 if (endp == linebuf || errno == ERANGE)
102 return -1;
103 return 0;
104}
105
106static int __compare(const void *t1, const void *t2)
107{
108 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
109 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
110 if (top1->pkg < top2->pkg)
111 return -1;
112 else if (top1->pkg > top2->pkg)
113 return 1;
114 else if (top1->core < top2->core)
115 return -1;
116 else if (top1->core > top2->core)
117 return 1;
118 else if (top1->cpu < top2->cpu)
119 return -1;
120 else if (top1->cpu > top2->cpu)
121 return 1;
122 else
123 return 0;
124}
125
126/*
127 * Returns amount of cpus, negative on error, cpu_top must be
128 * passed to cpu_topology_release to free resources
129 *
130 * Array is sorted after ->pkg, ->core, then ->cpu
131 */
132int get_cpu_topology(struct cpupower_topology *cpu_top)
133{
134 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
135
136 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
137 if (cpu_top->core_info == NULL)
138 return -ENOMEM;
139 cpu_top->pkgs = cpu_top->cores = 0;
140 for (cpu = 0; cpu < cpus; cpu++) {
141 cpu_top->core_info[cpu].cpu = cpu;
142 cpu_top->core_info[cpu].is_online = cpupower_is_cpu_online(cpu);
143 if(sysfs_topology_read_file(
144 cpu,
145 "physical_package_id",
146 &(cpu_top->core_info[cpu].pkg)) < 0) {
147 cpu_top->core_info[cpu].pkg = -1;
148 cpu_top->core_info[cpu].core = -1;
149 continue;
150 }
151 if(sysfs_topology_read_file(
152 cpu,
153 "core_id",
154 &(cpu_top->core_info[cpu].core)) < 0) {
155 cpu_top->core_info[cpu].pkg = -1;
156 cpu_top->core_info[cpu].core = -1;
157 continue;
158 }
159 }
160
161 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
162 __compare);
163
164 /* Count the number of distinct pkgs values. This works
165 because the primary sort of the core_info struct was just
166 done by pkg value. */
167 last_pkg = cpu_top->core_info[0].pkg;
168 for(cpu = 1; cpu < cpus; cpu++) {
169 if (cpu_top->core_info[cpu].pkg != last_pkg &&
170 cpu_top->core_info[cpu].pkg != -1) {
171
172 last_pkg = cpu_top->core_info[cpu].pkg;
173 cpu_top->pkgs++;
174 }
175 }
176 if (!(cpu_top->core_info[0].pkg == -1))
177 cpu_top->pkgs++;
178
179 /* Intel's cores count is not consecutively numbered, there may
180 * be a core_id of 3, but none of 2. Assume there always is 0
181 * Get amount of cores by counting duplicates in a package
182 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
183 if (cpu_top->core_info[cpu].core == 0)
184 cpu_top->cores++;
185 */
186 return cpus;
187}
188
189void cpu_topology_release(struct cpupower_topology cpu_top)
190{
191 free(cpu_top.core_info);
192}
diff --git a/tools/power/cpupower/lib/cpupower.h b/tools/power/cpupower/lib/cpupower.h
new file mode 100644
index 000000000000..fa031fcc7710
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.h
@@ -0,0 +1,35 @@
1#ifndef __CPUPOWER_CPUPOWER_H__
2#define __CPUPOWER_CPUPOWER_H__
3
4struct cpupower_topology {
5 /* Amount of CPU cores, packages and threads per core in the system */
6 unsigned int cores;
7 unsigned int pkgs;
8 unsigned int threads; /* per core */
9
10 /* Array gets mallocated with cores entries, holding per core info */
11 struct cpuid_core_info *core_info;
12};
13
14struct cpuid_core_info {
15 int pkg;
16 int core;
17 int cpu;
18
19 /* flags */
20 unsigned int is_online:1;
21};
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27int get_cpu_topology(struct cpupower_topology *cpu_top);
28void cpu_topology_release(struct cpupower_topology cpu_top);
29int cpupower_is_cpu_online(unsigned int cpu);
30
31#ifdef __cplusplus
32}
33#endif
34
35#endif
diff --git a/tools/power/cpupower/lib/cpupower_intern.h b/tools/power/cpupower/lib/cpupower_intern.h
new file mode 100644
index 000000000000..f8ec4009621c
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower_intern.h
@@ -0,0 +1,5 @@
1#define PATH_TO_CPU "/sys/devices/system/cpu/"
2#define MAX_LINE_LEN 4096
3#define SYSFS_PATH_MAX 255
4
5unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
deleted file mode 100644
index 870713a75a81..000000000000
--- a/tools/power/cpupower/lib/sysfs.c
+++ /dev/null
@@ -1,672 +0,0 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <stdio.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <limits.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpufreq.h"
18
19#define PATH_TO_CPU "/sys/devices/system/cpu/"
20#define MAX_LINE_LEN 4096
21#define SYSFS_PATH_MAX 255
22
23
24static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
25{
26 int fd;
27 ssize_t numread;
28
29 fd = open(path, O_RDONLY);
30 if (fd == -1)
31 return 0;
32
33 numread = read(fd, buf, buflen - 1);
34 if (numread < 1) {
35 close(fd);
36 return 0;
37 }
38
39 buf[numread] = '\0';
40 close(fd);
41
42 return (unsigned int) numread;
43}
44
45
46/* CPUFREQ sysfs access **************************************************/
47
48/* helper function to read file from /sys into given buffer */
49/* fname is a relative path under "cpuX/cpufreq" dir */
50static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
51 char *buf, size_t buflen)
52{
53 char path[SYSFS_PATH_MAX];
54
55 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
56 cpu, fname);
57 return sysfs_read_file(path, buf, buflen);
58}
59
60/* helper function to write a new value to a /sys file */
61/* fname is a relative path under "cpuX/cpufreq" dir */
62static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
63 const char *fname,
64 const char *value, size_t len)
65{
66 char path[SYSFS_PATH_MAX];
67 int fd;
68 ssize_t numwrite;
69
70 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
71 cpu, fname);
72
73 fd = open(path, O_WRONLY);
74 if (fd == -1)
75 return 0;
76
77 numwrite = write(fd, value, len);
78 if (numwrite < 1) {
79 close(fd);
80 return 0;
81 }
82
83 close(fd);
84
85 return (unsigned int) numwrite;
86}
87
88/* read access to files which contain one numeric value */
89
90enum cpufreq_value {
91 CPUINFO_CUR_FREQ,
92 CPUINFO_MIN_FREQ,
93 CPUINFO_MAX_FREQ,
94 CPUINFO_LATENCY,
95 SCALING_CUR_FREQ,
96 SCALING_MIN_FREQ,
97 SCALING_MAX_FREQ,
98 STATS_NUM_TRANSITIONS,
99 MAX_CPUFREQ_VALUE_READ_FILES
100};
101
102static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
107 [SCALING_CUR_FREQ] = "scaling_cur_freq",
108 [SCALING_MIN_FREQ] = "scaling_min_freq",
109 [SCALING_MAX_FREQ] = "scaling_max_freq",
110 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111};
112
113
114static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115 enum cpufreq_value which)
116{
117 unsigned long value;
118 unsigned int len;
119 char linebuf[MAX_LINE_LEN];
120 char *endp;
121
122 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123 return 0;
124
125 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126 linebuf, sizeof(linebuf));
127
128 if (len == 0)
129 return 0;
130
131 value = strtoul(linebuf, &endp, 0);
132
133 if (endp == linebuf || errno == ERANGE)
134 return 0;
135
136 return value;
137}
138
139/* read access to files which contain one string */
140
141enum cpufreq_string {
142 SCALING_DRIVER,
143 SCALING_GOVERNOR,
144 MAX_CPUFREQ_STRING_FILES
145};
146
147static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148 [SCALING_DRIVER] = "scaling_driver",
149 [SCALING_GOVERNOR] = "scaling_governor",
150};
151
152
153static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154 enum cpufreq_string which)
155{
156 char linebuf[MAX_LINE_LEN];
157 char *result;
158 unsigned int len;
159
160 if (which >= MAX_CPUFREQ_STRING_FILES)
161 return NULL;
162
163 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164 linebuf, sizeof(linebuf));
165 if (len == 0)
166 return NULL;
167
168 result = strdup(linebuf);
169 if (result == NULL)
170 return NULL;
171
172 if (result[strlen(result) - 1] == '\n')
173 result[strlen(result) - 1] = '\0';
174
175 return result;
176}
177
178/* write access */
179
180enum cpufreq_write {
181 WRITE_SCALING_MIN_FREQ,
182 WRITE_SCALING_MAX_FREQ,
183 WRITE_SCALING_GOVERNOR,
184 WRITE_SCALING_SET_SPEED,
185 MAX_CPUFREQ_WRITE_FILES
186};
187
188static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193};
194
195static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196 enum cpufreq_write which,
197 const char *new_value, size_t len)
198{
199 if (which >= MAX_CPUFREQ_WRITE_FILES)
200 return 0;
201
202 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203 new_value, len) != len)
204 return -ENODEV;
205
206 return 0;
207};
208
209unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210{
211 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212}
213
214unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215{
216 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217}
218
219unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220{
221 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222}
223
224int sysfs_get_freq_hardware_limits(unsigned int cpu,
225 unsigned long *min,
226 unsigned long *max)
227{
228 if ((!min) || (!max))
229 return -EINVAL;
230
231 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232 if (!*min)
233 return -ENODEV;
234
235 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236 if (!*max)
237 return -ENODEV;
238
239 return 0;
240}
241
242char *sysfs_get_freq_driver(unsigned int cpu)
243{
244 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245}
246
247struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248{
249 struct cpufreq_policy *policy;
250
251 policy = malloc(sizeof(struct cpufreq_policy));
252 if (!policy)
253 return NULL;
254
255 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256 if (!policy->governor) {
257 free(policy);
258 return NULL;
259 }
260 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262 if ((!policy->min) || (!policy->max)) {
263 free(policy->governor);
264 free(policy);
265 return NULL;
266 }
267
268 return policy;
269}
270
271struct cpufreq_available_governors *
272sysfs_get_freq_available_governors(unsigned int cpu) {
273 struct cpufreq_available_governors *first = NULL;
274 struct cpufreq_available_governors *current = NULL;
275 char linebuf[MAX_LINE_LEN];
276 unsigned int pos, i;
277 unsigned int len;
278
279 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280 linebuf, sizeof(linebuf));
281 if (len == 0)
282 return NULL;
283
284 pos = 0;
285 for (i = 0; i < len; i++) {
286 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287 if (i - pos < 2)
288 continue;
289 if (current) {
290 current->next = malloc(sizeof(*current));
291 if (!current->next)
292 goto error_out;
293 current = current->next;
294 } else {
295 first = malloc(sizeof(*first));
296 if (!first)
297 goto error_out;
298 current = first;
299 }
300 current->first = first;
301 current->next = NULL;
302
303 current->governor = malloc(i - pos + 1);
304 if (!current->governor)
305 goto error_out;
306
307 memcpy(current->governor, linebuf + pos, i - pos);
308 current->governor[i - pos] = '\0';
309 pos = i + 1;
310 }
311 }
312
313 return first;
314
315 error_out:
316 while (first) {
317 current = first->next;
318 if (first->governor)
319 free(first->governor);
320 free(first);
321 first = current;
322 }
323 return NULL;
324}
325
326
327struct cpufreq_available_frequencies *
328sysfs_get_available_frequencies(unsigned int cpu) {
329 struct cpufreq_available_frequencies *first = NULL;
330 struct cpufreq_available_frequencies *current = NULL;
331 char one_value[SYSFS_PATH_MAX];
332 char linebuf[MAX_LINE_LEN];
333 unsigned int pos, i;
334 unsigned int len;
335
336 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337 linebuf, sizeof(linebuf));
338 if (len == 0)
339 return NULL;
340
341 pos = 0;
342 for (i = 0; i < len; i++) {
343 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344 if (i - pos < 2)
345 continue;
346 if (i - pos >= SYSFS_PATH_MAX)
347 goto error_out;
348 if (current) {
349 current->next = malloc(sizeof(*current));
350 if (!current->next)
351 goto error_out;
352 current = current->next;
353 } else {
354 first = malloc(sizeof(*first));
355 if (!first)
356 goto error_out;
357 current = first;
358 }
359 current->first = first;
360 current->next = NULL;
361
362 memcpy(one_value, linebuf + pos, i - pos);
363 one_value[i - pos] = '\0';
364 if (sscanf(one_value, "%lu", &current->frequency) != 1)
365 goto error_out;
366
367 pos = i + 1;
368 }
369 }
370
371 return first;
372
373 error_out:
374 while (first) {
375 current = first->next;
376 free(first);
377 first = current;
378 }
379 return NULL;
380}
381
382static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383 const char *file)
384{
385 struct cpufreq_affected_cpus *first = NULL;
386 struct cpufreq_affected_cpus *current = NULL;
387 char one_value[SYSFS_PATH_MAX];
388 char linebuf[MAX_LINE_LEN];
389 unsigned int pos, i;
390 unsigned int len;
391
392 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393 if (len == 0)
394 return NULL;
395
396 pos = 0;
397 for (i = 0; i < len; i++) {
398 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399 if (i - pos < 1)
400 continue;
401 if (i - pos >= SYSFS_PATH_MAX)
402 goto error_out;
403 if (current) {
404 current->next = malloc(sizeof(*current));
405 if (!current->next)
406 goto error_out;
407 current = current->next;
408 } else {
409 first = malloc(sizeof(*first));
410 if (!first)
411 goto error_out;
412 current = first;
413 }
414 current->first = first;
415 current->next = NULL;
416
417 memcpy(one_value, linebuf + pos, i - pos);
418 one_value[i - pos] = '\0';
419
420 if (sscanf(one_value, "%u", &current->cpu) != 1)
421 goto error_out;
422
423 pos = i + 1;
424 }
425 }
426
427 return first;
428
429 error_out:
430 while (first) {
431 current = first->next;
432 free(first);
433 first = current;
434 }
435 return NULL;
436}
437
438struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439{
440 return sysfs_get_cpu_list(cpu, "affected_cpus");
441}
442
443struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444{
445 return sysfs_get_cpu_list(cpu, "related_cpus");
446}
447
448struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449 unsigned long long *total_time) {
450 struct cpufreq_stats *first = NULL;
451 struct cpufreq_stats *current = NULL;
452 char one_value[SYSFS_PATH_MAX];
453 char linebuf[MAX_LINE_LEN];
454 unsigned int pos, i;
455 unsigned int len;
456
457 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458 linebuf, sizeof(linebuf));
459 if (len == 0)
460 return NULL;
461
462 *total_time = 0;
463 pos = 0;
464 for (i = 0; i < len; i++) {
465 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466 if (i - pos < 2)
467 continue;
468 if ((i - pos) >= SYSFS_PATH_MAX)
469 goto error_out;
470 if (current) {
471 current->next = malloc(sizeof(*current));
472 if (!current->next)
473 goto error_out;
474 current = current->next;
475 } else {
476 first = malloc(sizeof(*first));
477 if (!first)
478 goto error_out;
479 current = first;
480 }
481 current->first = first;
482 current->next = NULL;
483
484 memcpy(one_value, linebuf + pos, i - pos);
485 one_value[i - pos] = '\0';
486 if (sscanf(one_value, "%lu %llu",
487 &current->frequency,
488 &current->time_in_state) != 2)
489 goto error_out;
490
491 *total_time = *total_time + current->time_in_state;
492 pos = i + 1;
493 }
494 }
495
496 return first;
497
498 error_out:
499 while (first) {
500 current = first->next;
501 free(first);
502 first = current;
503 }
504 return NULL;
505}
506
507unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508{
509 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510}
511
512static int verify_gov(char *new_gov, char *passed_gov)
513{
514 unsigned int i, j = 0;
515
516 if (!passed_gov || (strlen(passed_gov) > 19))
517 return -EINVAL;
518
519 strncpy(new_gov, passed_gov, 20);
520 for (i = 0; i < 20; i++) {
521 if (j) {
522 new_gov[i] = '\0';
523 continue;
524 }
525 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526 continue;
527
528 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529 continue;
530
531 if (new_gov[i] == '-')
532 continue;
533
534 if (new_gov[i] == '_')
535 continue;
536
537 if (new_gov[i] == '\0') {
538 j = 1;
539 continue;
540 }
541 return -EINVAL;
542 }
543 new_gov[19] = '\0';
544 return 0;
545}
546
547int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548{
549 char new_gov[SYSFS_PATH_MAX];
550
551 if (!governor)
552 return -EINVAL;
553
554 if (verify_gov(new_gov, governor))
555 return -EINVAL;
556
557 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558 new_gov, strlen(new_gov));
559};
560
561int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562{
563 char value[SYSFS_PATH_MAX];
564
565 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566
567 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568 value, strlen(value));
569};
570
571
572int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573{
574 char value[SYSFS_PATH_MAX];
575
576 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577
578 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579 value, strlen(value));
580};
581
582
583int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584{
585 char min[SYSFS_PATH_MAX];
586 char max[SYSFS_PATH_MAX];
587 char gov[SYSFS_PATH_MAX];
588 int ret;
589 unsigned long old_min;
590 int write_max_first;
591
592 if (!policy || !(policy->governor))
593 return -EINVAL;
594
595 if (policy->max < policy->min)
596 return -EINVAL;
597
598 if (verify_gov(gov, policy->governor))
599 return -EINVAL;
600
601 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603
604 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606
607 if (write_max_first) {
608 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609 max, strlen(max));
610 if (ret)
611 return ret;
612 }
613
614 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615 strlen(min));
616 if (ret)
617 return ret;
618
619 if (!write_max_first) {
620 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621 max, strlen(max));
622 if (ret)
623 return ret;
624 }
625
626 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627 gov, strlen(gov));
628}
629
630int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631{
632 struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633 char userspace_gov[] = "userspace";
634 char freq[SYSFS_PATH_MAX];
635 int ret;
636
637 if (!pol)
638 return -ENODEV;
639
640 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642 if (ret) {
643 cpufreq_put_policy(pol);
644 return ret;
645 }
646 }
647
648 cpufreq_put_policy(pol);
649
650 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651
652 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653 freq, strlen(freq));
654}
655
656/* CPUFREQ sysfs access **************************************************/
657
658/* General sysfs access **************************************************/
659int sysfs_cpu_exists(unsigned int cpu)
660{
661 char file[SYSFS_PATH_MAX];
662 struct stat statbuf;
663
664 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665
666 if (stat(file, &statbuf) != 0)
667 return -ENOSYS;
668
669 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670}
671
672/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
deleted file mode 100644
index c76a5e0af501..000000000000
--- a/tools/power/cpupower/lib/sysfs.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* General */
2extern unsigned int sysfs_cpu_exists(unsigned int cpu);
3
4/* CPUfreq */
5extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
6extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
7extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
8extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
9 unsigned long *min, unsigned long *max);
10extern char *sysfs_get_freq_driver(unsigned int cpu);
11extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
12extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
13 unsigned int cpu);
14extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
15 unsigned int cpu);
16extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
17 unsigned int cpu);
18extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
19 unsigned int cpu);
20extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
21 unsigned long long *total_time);
22extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
23extern int sysfs_set_freq_policy(unsigned int cpu,
24 struct cpufreq_policy *policy);
25extern int sysfs_modify_freq_policy_min(unsigned int cpu,
26 unsigned long min_freq);
27extern int sysfs_modify_freq_policy_max(unsigned int cpu,
28 unsigned long max_freq);
29extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
30extern int sysfs_set_frequency(unsigned int cpu,
31 unsigned long target_frequency);
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
index 9c85a382e355..6aa8d239dff9 100644
--- a/tools/power/cpupower/man/cpupower-frequency-info.1
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information 4cpupower\-frequency\-info \- Utility to retrieve cpufreq kernel information
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
index 3eacc8d03d1a..b50570221a5b 100644
--- a/tools/power/cpupower/man/cpupower-frequency-set.1
+++ b/tools/power/cpupower/man/cpupower-frequency-set.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. 4cpupower\-frequency\-set \- A small tool which allows to modify cpufreq settings.
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP] 7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1
index 7b3646adb92f..80a1311fa747 100644
--- a/tools/power/cpupower/man/cpupower-idle-info.1
+++ b/tools/power/cpupower/man/cpupower-idle-info.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower idle\-info \- Utility to retrieve cpu idle kernel information 4cpupower\-idle\-info \- Utility to retrieve cpu idle kernel information
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-idle-set.1 b/tools/power/cpupower/man/cpupower-idle-set.1
index 580c4e3ea92a..21916cff7516 100644
--- a/tools/power/cpupower/man/cpupower-idle-set.1
+++ b/tools/power/cpupower/man/cpupower-idle-set.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER-IDLE-SET" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER-IDLE-SET" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower idle\-set \- Utility to set cpu idle state specific kernel options 4cpupower\-idle\-set \- Utility to set cpu idle state specific kernel options
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index 0fbd1a22c0a9..b4bf76971dc9 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -16,8 +16,8 @@
16#include <getopt.h> 16#include <getopt.h>
17 17
18#include "cpufreq.h" 18#include "cpufreq.h"
19#include "cpuidle.h"
19#include "helpers/helpers.h" 20#include "helpers/helpers.h"
20#include "helpers/sysfs.h"
21 21
22#define NORM_FREQ_LEN 32 22#define NORM_FREQ_LEN 32
23 23
@@ -296,7 +296,7 @@ int cmd_freq_set(int argc, char **argv)
296 struct cpufreq_affected_cpus *cpus; 296 struct cpufreq_affected_cpus *cpus;
297 297
298 if (!bitmask_isbitset(cpus_chosen, cpu) || 298 if (!bitmask_isbitset(cpus_chosen, cpu) ||
299 cpufreq_cpu_exists(cpu)) 299 cpupower_is_cpu_online(cpu))
300 continue; 300 continue;
301 301
302 cpus = cpufreq_get_related_cpus(cpu); 302 cpus = cpufreq_get_related_cpus(cpu);
@@ -316,10 +316,10 @@ int cmd_freq_set(int argc, char **argv)
316 cpu <= bitmask_last(cpus_chosen); cpu++) { 316 cpu <= bitmask_last(cpus_chosen); cpu++) {
317 317
318 if (!bitmask_isbitset(cpus_chosen, cpu) || 318 if (!bitmask_isbitset(cpus_chosen, cpu) ||
319 cpufreq_cpu_exists(cpu)) 319 cpupower_is_cpu_online(cpu))
320 continue; 320 continue;
321 321
322 if (sysfs_is_cpu_online(cpu) != 1) 322 if (cpupower_is_cpu_online(cpu) != 1)
323 continue; 323 continue;
324 324
325 printf(_("Setting cpu: %d\n"), cpu); 325 printf(_("Setting cpu: %d\n"), cpu);
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index 8bf8ab5ffa25..b59c85defa05 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -13,8 +13,10 @@
13#include <string.h> 13#include <string.h>
14#include <getopt.h> 14#include <getopt.h>
15 15
16#include "helpers/helpers.h" 16#include <cpuidle.h>
17
17#include "helpers/sysfs.h" 18#include "helpers/sysfs.h"
19#include "helpers/helpers.h"
18#include "helpers/bitmask.h" 20#include "helpers/bitmask.h"
19 21
20#define LINE_LEN 10 22#define LINE_LEN 10
@@ -24,7 +26,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24 unsigned int idlestates, idlestate; 26 unsigned int idlestates, idlestate;
25 char *tmp; 27 char *tmp;
26 28
27 idlestates = sysfs_get_idlestate_count(cpu); 29 idlestates = cpuidle_state_count(cpu);
28 if (idlestates == 0) { 30 if (idlestates == 0) {
29 printf(_("CPU %u: No idle states\n"), cpu); 31 printf(_("CPU %u: No idle states\n"), cpu);
30 return; 32 return;
@@ -33,7 +35,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
33 printf(_("Number of idle states: %d\n"), idlestates); 35 printf(_("Number of idle states: %d\n"), idlestates);
34 printf(_("Available idle states:")); 36 printf(_("Available idle states:"));
35 for (idlestate = 0; idlestate < idlestates; idlestate++) { 37 for (idlestate = 0; idlestate < idlestates; idlestate++) {
36 tmp = sysfs_get_idlestate_name(cpu, idlestate); 38 tmp = cpuidle_state_name(cpu, idlestate);
37 if (!tmp) 39 if (!tmp)
38 continue; 40 continue;
39 printf(" %s", tmp); 41 printf(" %s", tmp);
@@ -45,28 +47,28 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
45 return; 47 return;
46 48
47 for (idlestate = 0; idlestate < idlestates; idlestate++) { 49 for (idlestate = 0; idlestate < idlestates; idlestate++) {
48 int disabled = sysfs_is_idlestate_disabled(cpu, idlestate); 50 int disabled = cpuidle_is_state_disabled(cpu, idlestate);
49 /* Disabled interface not supported on older kernels */ 51 /* Disabled interface not supported on older kernels */
50 if (disabled < 0) 52 if (disabled < 0)
51 disabled = 0; 53 disabled = 0;
52 tmp = sysfs_get_idlestate_name(cpu, idlestate); 54 tmp = cpuidle_state_name(cpu, idlestate);
53 if (!tmp) 55 if (!tmp)
54 continue; 56 continue;
55 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : ""); 57 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
56 free(tmp); 58 free(tmp);
57 59
58 tmp = sysfs_get_idlestate_desc(cpu, idlestate); 60 tmp = cpuidle_state_desc(cpu, idlestate);
59 if (!tmp) 61 if (!tmp)
60 continue; 62 continue;
61 printf(_("Flags/Description: %s\n"), tmp); 63 printf(_("Flags/Description: %s\n"), tmp);
62 free(tmp); 64 free(tmp);
63 65
64 printf(_("Latency: %lu\n"), 66 printf(_("Latency: %lu\n"),
65 sysfs_get_idlestate_latency(cpu, idlestate)); 67 cpuidle_state_latency(cpu, idlestate));
66 printf(_("Usage: %lu\n"), 68 printf(_("Usage: %lu\n"),
67 sysfs_get_idlestate_usage(cpu, idlestate)); 69 cpuidle_state_usage(cpu, idlestate));
68 printf(_("Duration: %llu\n"), 70 printf(_("Duration: %llu\n"),
69 sysfs_get_idlestate_time(cpu, idlestate)); 71 cpuidle_state_time(cpu, idlestate));
70 } 72 }
71} 73}
72 74
@@ -74,7 +76,7 @@ static void cpuidle_general_output(void)
74{ 76{
75 char *tmp; 77 char *tmp;
76 78
77 tmp = sysfs_get_cpuidle_driver(); 79 tmp = cpuidle_get_driver();
78 if (!tmp) { 80 if (!tmp) {
79 printf(_("Could not determine cpuidle driver\n")); 81 printf(_("Could not determine cpuidle driver\n"));
80 return; 82 return;
@@ -83,7 +85,7 @@ static void cpuidle_general_output(void)
83 printf(_("CPUidle driver: %s\n"), tmp); 85 printf(_("CPUidle driver: %s\n"), tmp);
84 free(tmp); 86 free(tmp);
85 87
86 tmp = sysfs_get_cpuidle_governor(); 88 tmp = cpuidle_get_governor();
87 if (!tmp) { 89 if (!tmp) {
88 printf(_("Could not determine cpuidle governor\n")); 90 printf(_("Could not determine cpuidle governor\n"));
89 return; 91 return;
@@ -98,7 +100,7 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
98 long max_allowed_cstate = 2000000000; 100 long max_allowed_cstate = 2000000000;
99 unsigned int cstate, cstates; 101 unsigned int cstate, cstates;
100 102
101 cstates = sysfs_get_idlestate_count(cpu); 103 cstates = cpuidle_state_count(cpu);
102 if (cstates == 0) { 104 if (cstates == 0) {
103 printf(_("CPU %u: No C-states info\n"), cpu); 105 printf(_("CPU %u: No C-states info\n"), cpu);
104 return; 106 return;
@@ -113,11 +115,11 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
113 "type[C%d] "), cstate, cstate); 115 "type[C%d] "), cstate, cstate);
114 printf(_("promotion[--] demotion[--] ")); 116 printf(_("promotion[--] demotion[--] "));
115 printf(_("latency[%03lu] "), 117 printf(_("latency[%03lu] "),
116 sysfs_get_idlestate_latency(cpu, cstate)); 118 cpuidle_state_latency(cpu, cstate));
117 printf(_("usage[%08lu] "), 119 printf(_("usage[%08lu] "),
118 sysfs_get_idlestate_usage(cpu, cstate)); 120 cpuidle_state_usage(cpu, cstate));
119 printf(_("duration[%020Lu] \n"), 121 printf(_("duration[%020Lu] \n"),
120 sysfs_get_idlestate_time(cpu, cstate)); 122 cpuidle_state_time(cpu, cstate));
121 } 123 }
122} 124}
123 125
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index d6b6ae44b8c2..691c24d50ef4 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -5,12 +5,12 @@
5#include <limits.h> 5#include <limits.h>
6#include <string.h> 6#include <string.h>
7#include <ctype.h> 7#include <ctype.h>
8
9#include <getopt.h> 8#include <getopt.h>
10 9
11#include "cpufreq.h" 10#include <cpufreq.h>
11#include <cpuidle.h>
12
12#include "helpers/helpers.h" 13#include "helpers/helpers.h"
13#include "helpers/sysfs.h"
14 14
15static struct option info_opts[] = { 15static struct option info_opts[] = {
16 {"disable", required_argument, NULL, 'd'}, 16 {"disable", required_argument, NULL, 'd'},
@@ -104,16 +104,16 @@ int cmd_idle_set(int argc, char **argv)
104 if (!bitmask_isbitset(cpus_chosen, cpu)) 104 if (!bitmask_isbitset(cpus_chosen, cpu))
105 continue; 105 continue;
106 106
107 if (sysfs_is_cpu_online(cpu) != 1) 107 if (cpupower_is_cpu_online(cpu) != 1)
108 continue; 108 continue;
109 109
110 idlestates = sysfs_get_idlestate_count(cpu); 110 idlestates = cpuidle_state_count(cpu);
111 if (idlestates <= 0) 111 if (idlestates <= 0)
112 continue; 112 continue;
113 113
114 switch (param) { 114 switch (param) {
115 case 'd': 115 case 'd':
116 ret = sysfs_idlestate_disable(cpu, idlestate, 1); 116 ret = cpuidle_state_disable(cpu, idlestate, 1);
117 if (ret == 0) 117 if (ret == 0)
118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
119 else if (ret == -1) 119 else if (ret == -1)
@@ -126,7 +126,7 @@ int cmd_idle_set(int argc, char **argv)
126 idlestate, cpu); 126 idlestate, cpu);
127 break; 127 break;
128 case 'e': 128 case 'e':
129 ret = sysfs_idlestate_disable(cpu, idlestate, 0); 129 ret = cpuidle_state_disable(cpu, idlestate, 0);
130 if (ret == 0) 130 if (ret == 0)
131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
132 else if (ret == -1) 132 else if (ret == -1)
@@ -140,13 +140,13 @@ int cmd_idle_set(int argc, char **argv)
140 break; 140 break;
141 case 'D': 141 case 'D':
142 for (idlestate = 0; idlestate < idlestates; idlestate++) { 142 for (idlestate = 0; idlestate < idlestates; idlestate++) {
143 disabled = sysfs_is_idlestate_disabled 143 disabled = cpuidle_is_state_disabled
144 (cpu, idlestate); 144 (cpu, idlestate);
145 state_latency = sysfs_get_idlestate_latency 145 state_latency = cpuidle_state_latency
146 (cpu, idlestate); 146 (cpu, idlestate);
147 if (disabled == 1) { 147 if (disabled == 1) {
148 if (latency > state_latency){ 148 if (latency > state_latency){
149 ret = sysfs_idlestate_disable 149 ret = cpuidle_state_disable
150 (cpu, idlestate, 0); 150 (cpu, idlestate, 0);
151 if (ret == 0) 151 if (ret == 0)
152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
@@ -154,7 +154,7 @@ int cmd_idle_set(int argc, char **argv)
154 continue; 154 continue;
155 } 155 }
156 if (latency <= state_latency){ 156 if (latency <= state_latency){
157 ret = sysfs_idlestate_disable 157 ret = cpuidle_state_disable
158 (cpu, idlestate, 1); 158 (cpu, idlestate, 1);
159 if (ret == 0) 159 if (ret == 0)
160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
@@ -163,10 +163,10 @@ int cmd_idle_set(int argc, char **argv)
163 break; 163 break;
164 case 'E': 164 case 'E':
165 for (idlestate = 0; idlestate < idlestates; idlestate++) { 165 for (idlestate = 0; idlestate < idlestates; idlestate++) {
166 disabled = sysfs_is_idlestate_disabled 166 disabled = cpuidle_is_state_disabled
167 (cpu, idlestate); 167 (cpu, idlestate);
168 if (disabled == 1) { 168 if (disabled == 1) {
169 ret = sysfs_idlestate_disable 169 ret = cpuidle_state_disable
170 (cpu, idlestate, 0); 170 (cpu, idlestate, 0);
171 if (ret == 0) 171 if (ret == 0)
172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index aa9e95486a2d..afb66f80554e 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -14,6 +14,7 @@
14#include <locale.h> 14#include <locale.h>
15 15
16#include "helpers/bitmask.h" 16#include "helpers/bitmask.h"
17#include <cpupower.h>
17 18
18/* Internationalization ****************************/ 19/* Internationalization ****************************/
19#ifdef NLS 20#ifdef NLS
@@ -92,31 +93,6 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info; 93extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/ 94/* cpuid and cpuinfo helpers **************************/
94 95
95struct cpuid_core_info {
96 int pkg;
97 int core;
98 int cpu;
99
100 /* flags */
101 unsigned int is_online:1;
102};
103
104/* CPU topology/hierarchy parsing ******************/
105struct cpupower_topology {
106 /* Amount of CPU cores, packages and threads per core in the system */
107 unsigned int cores;
108 unsigned int pkgs;
109 unsigned int threads; /* per core */
110
111 /* Array gets mallocated with cores entries, holding per core info */
112 struct cpuid_core_info *core_info;
113};
114
115extern int get_cpu_topology(struct cpupower_topology *cpu_top);
116extern void cpu_topology_release(struct cpupower_topology cpu_top);
117
118/* CPU topology/hierarchy parsing ******************/
119
120/* X86 ONLY ****************************************/ 96/* X86 ONLY ****************************************/
121#if defined(__i386__) || defined(__x86_64__) 97#if defined(__i386__) || defined(__x86_64__)
122 98
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index 5f9c908f4557..a1a6c6041a1e 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -16,110 +16,7 @@
16#include <errno.h> 16#include <errno.h>
17#include <fcntl.h> 17#include <fcntl.h>
18 18
19#include <helpers/helpers.h> 19#include <cpuidle.h>
20#include <helpers/sysfs.h>
21 20
22/* returns -1 on failure, 0 on success */ 21/* CPU topology/hierarchy parsing ******************/
23static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
24{
25 char linebuf[MAX_LINE_LEN];
26 char *endp;
27 char path[SYSFS_PATH_MAX];
28 22
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
30 cpu, fname);
31 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
32 return -1;
33 *result = strtol(linebuf, &endp, 0);
34 if (endp == linebuf || errno == ERANGE)
35 return -1;
36 return 0;
37}
38
39static int __compare(const void *t1, const void *t2)
40{
41 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
42 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
43 if (top1->pkg < top2->pkg)
44 return -1;
45 else if (top1->pkg > top2->pkg)
46 return 1;
47 else if (top1->core < top2->core)
48 return -1;
49 else if (top1->core > top2->core)
50 return 1;
51 else if (top1->cpu < top2->cpu)
52 return -1;
53 else if (top1->cpu > top2->cpu)
54 return 1;
55 else
56 return 0;
57}
58
59/*
60 * Returns amount of cpus, negative on error, cpu_top must be
61 * passed to cpu_topology_release to free resources
62 *
63 * Array is sorted after ->pkg, ->core, then ->cpu
64 */
65int get_cpu_topology(struct cpupower_topology *cpu_top)
66{
67 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
68
69 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
70 if (cpu_top->core_info == NULL)
71 return -ENOMEM;
72 cpu_top->pkgs = cpu_top->cores = 0;
73 for (cpu = 0; cpu < cpus; cpu++) {
74 cpu_top->core_info[cpu].cpu = cpu;
75 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
76 if(sysfs_topology_read_file(
77 cpu,
78 "physical_package_id",
79 &(cpu_top->core_info[cpu].pkg)) < 0) {
80 cpu_top->core_info[cpu].pkg = -1;
81 cpu_top->core_info[cpu].core = -1;
82 continue;
83 }
84 if(sysfs_topology_read_file(
85 cpu,
86 "core_id",
87 &(cpu_top->core_info[cpu].core)) < 0) {
88 cpu_top->core_info[cpu].pkg = -1;
89 cpu_top->core_info[cpu].core = -1;
90 continue;
91 }
92 }
93
94 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
95 __compare);
96
97 /* Count the number of distinct pkgs values. This works
98 because the primary sort of the core_info struct was just
99 done by pkg value. */
100 last_pkg = cpu_top->core_info[0].pkg;
101 for(cpu = 1; cpu < cpus; cpu++) {
102 if (cpu_top->core_info[cpu].pkg != last_pkg &&
103 cpu_top->core_info[cpu].pkg != -1) {
104
105 last_pkg = cpu_top->core_info[cpu].pkg;
106 cpu_top->pkgs++;
107 }
108 }
109 if (!(cpu_top->core_info[0].pkg == -1))
110 cpu_top->pkgs++;
111
112 /* Intel's cores count is not consecutively numbered, there may
113 * be a core_id of 3, but none of 2. Assume there always is 0
114 * Get amount of cores by counting duplicates in a package
115 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
116 if (cpu_top->core_info[cpu].core == 0)
117 cpu_top->cores++;
118 */
119 return cpus;
120}
121
122void cpu_topology_release(struct cpupower_topology cpu_top)
123{
124 free(cpu_top.core_info);
125}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
index bcd22a1a3970..1b5da0066ebf 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -10,8 +10,8 @@
10#include <stdint.h> 10#include <stdint.h>
11#include <string.h> 11#include <string.h>
12#include <limits.h> 12#include <limits.h>
13#include <cpuidle.h>
13 14
14#include "helpers/sysfs.h"
15#include "helpers/helpers.h" 15#include "helpers/helpers.h"
16#include "idle_monitor/cpupower-monitor.h" 16#include "idle_monitor/cpupower-monitor.h"
17 17
@@ -51,7 +51,7 @@ static int cpuidle_start(void)
51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52 state++) { 52 state++) {
53 previous_count[cpu][state] = 53 previous_count[cpu][state] =
54 sysfs_get_idlestate_time(cpu, state); 54 cpuidle_state_time(cpu, state);
55 dprint("CPU %d - State: %d - Val: %llu\n", 55 dprint("CPU %d - State: %d - Val: %llu\n",
56 cpu, state, previous_count[cpu][state]); 56 cpu, state, previous_count[cpu][state]);
57 } 57 }
@@ -70,7 +70,7 @@ static int cpuidle_stop(void)
70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71 state++) { 71 state++) {
72 current_count[cpu][state] = 72 current_count[cpu][state] =
73 sysfs_get_idlestate_time(cpu, state); 73 cpuidle_state_time(cpu, state);
74 dprint("CPU %d - State: %d - Val: %llu\n", 74 dprint("CPU %d - State: %d - Val: %llu\n",
75 cpu, state, previous_count[cpu][state]); 75 cpu, state, previous_count[cpu][state]);
76 } 76 }
@@ -132,13 +132,13 @@ static struct cpuidle_monitor *cpuidle_register(void)
132 char *tmp; 132 char *tmp;
133 133
134 /* Assume idle state count is the same for all CPUs */ 134 /* Assume idle state count is the same for all CPUs */
135 cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0); 135 cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(0);
136 136
137 if (cpuidle_sysfs_monitor.hw_states_num <= 0) 137 if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138 return NULL; 138 return NULL;
139 139
140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) { 140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141 tmp = sysfs_get_idlestate_name(0, num); 141 tmp = cpuidle_state_name(0, num);
142 if (tmp == NULL) 142 if (tmp == NULL)
143 continue; 143 continue;
144 144
@@ -146,7 +146,7 @@ static struct cpuidle_monitor *cpuidle_register(void)
146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1); 146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147 free(tmp); 147 free(tmp);
148 148
149 tmp = sysfs_get_idlestate_desc(0, num); 149 tmp = cpuidle_state_desc(0, num);
150 if (tmp == NULL) 150 if (tmp == NULL)
151 continue; 151 continue;
152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1); 152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index a34bfd0c8928..785985677159 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -7,6 +7,7 @@ ldflags-y += --wrap=ioremap_nocache
7ldflags-y += --wrap=iounmap 7ldflags-y += --wrap=iounmap
8ldflags-y += --wrap=memunmap 8ldflags-y += --wrap=memunmap
9ldflags-y += --wrap=__devm_request_region 9ldflags-y += --wrap=__devm_request_region
10ldflags-y += --wrap=__devm_release_region
10ldflags-y += --wrap=__request_region 11ldflags-y += --wrap=__request_region
11ldflags-y += --wrap=__release_region 12ldflags-y += --wrap=__release_region
12ldflags-y += --wrap=devm_memremap_pages 13ldflags-y += --wrap=devm_memremap_pages
@@ -15,6 +16,7 @@ ldflags-y += --wrap=phys_to_pfn_t
15DRIVERS := ../../../drivers 16DRIVERS := ../../../drivers
16NVDIMM_SRC := $(DRIVERS)/nvdimm 17NVDIMM_SRC := $(DRIVERS)/nvdimm
17ACPI_SRC := $(DRIVERS)/acpi 18ACPI_SRC := $(DRIVERS)/acpi
19DAX_SRC := $(DRIVERS)/dax
18 20
19obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o 21obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
20obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o 22obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
@@ -22,6 +24,8 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o
22obj-$(CONFIG_ND_BLK) += nd_blk.o 24obj-$(CONFIG_ND_BLK) += nd_blk.o
23obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o 25obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
24obj-$(CONFIG_ACPI_NFIT) += nfit.o 26obj-$(CONFIG_ACPI_NFIT) += nfit.o
27obj-$(CONFIG_DEV_DAX) += dax.o
28obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
25 29
26nfit-y := $(ACPI_SRC)/nfit.o 30nfit-y := $(ACPI_SRC)/nfit.o
27nfit-y += config_check.o 31nfit-y += config_check.o
@@ -38,6 +42,12 @@ nd_blk-y += config_check.o
38nd_e820-y := $(NVDIMM_SRC)/e820.o 42nd_e820-y := $(NVDIMM_SRC)/e820.o
39nd_e820-y += config_check.o 43nd_e820-y += config_check.o
40 44
45dax-y := $(DAX_SRC)/dax.o
46dax-y += config_check.o
47
48dax_pmem-y := $(DAX_SRC)/pmem.o
49dax_pmem-y += config_check.o
50
41libnvdimm-y := $(NVDIMM_SRC)/core.o 51libnvdimm-y := $(NVDIMM_SRC)/core.o
42libnvdimm-y += $(NVDIMM_SRC)/bus.o 52libnvdimm-y += $(NVDIMM_SRC)/bus.o
43libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o 53libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o
@@ -49,6 +59,7 @@ libnvdimm-y += $(NVDIMM_SRC)/label.o
49libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o 59libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o
50libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o 60libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
51libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o 61libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
62libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o
52libnvdimm-y += config_check.o 63libnvdimm-y += config_check.o
53 64
54obj-m += test/ 65obj-m += test/
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c
index f2c7615554eb..adf18bfeca00 100644
--- a/tools/testing/nvdimm/config_check.c
+++ b/tools/testing/nvdimm/config_check.c
@@ -12,4 +12,6 @@ void check(void)
12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); 12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); 13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); 14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
15 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX));
16 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX_PMEM));
15} 17}
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 0c1a7e65bb81..c842095f2801 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -239,13 +239,11 @@ struct resource *__wrap___devm_request_region(struct device *dev,
239} 239}
240EXPORT_SYMBOL(__wrap___devm_request_region); 240EXPORT_SYMBOL(__wrap___devm_request_region);
241 241
242void __wrap___release_region(struct resource *parent, resource_size_t start, 242static bool nfit_test_release_region(struct resource *parent,
243 resource_size_t n) 243 resource_size_t start, resource_size_t n)
244{ 244{
245 struct nfit_test_resource *nfit_res;
246
247 if (parent == &iomem_resource) { 245 if (parent == &iomem_resource) {
248 nfit_res = get_nfit_res(start); 246 struct nfit_test_resource *nfit_res = get_nfit_res(start);
249 if (nfit_res) { 247 if (nfit_res) {
250 struct resource *res = nfit_res->res + 1; 248 struct resource *res = nfit_res->res + 1;
251 249
@@ -254,11 +252,26 @@ void __wrap___release_region(struct resource *parent, resource_size_t start,
254 __func__, start, n, res); 252 __func__, start, n, res);
255 else 253 else
256 memset(res, 0, sizeof(*res)); 254 memset(res, 0, sizeof(*res));
257 return; 255 return true;
258 } 256 }
259 } 257 }
260 __release_region(parent, start, n); 258 return false;
259}
260
261void __wrap___release_region(struct resource *parent, resource_size_t start,
262 resource_size_t n)
263{
264 if (!nfit_test_release_region(parent, start, n))
265 __release_region(parent, start, n);
261} 266}
262EXPORT_SYMBOL(__wrap___release_region); 267EXPORT_SYMBOL(__wrap___release_region);
263 268
269void __wrap___devm_release_region(struct device *dev, struct resource *parent,
270 resource_size_t start, resource_size_t n)
271{
272 if (!nfit_test_release_region(parent, start, n))
273 __devm_release_region(dev, parent, start, n);
274}
275EXPORT_SYMBOL(__wrap___devm_release_region);
276
264MODULE_LICENSE("GPL v2"); 277MODULE_LICENSE("GPL v2");
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 3187322eeed7..c919866853a0 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -330,12 +330,49 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
330 return 0; 330 return 0;
331} 331}
332 332
333static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
334{
335 static const struct nd_smart_payload smart_data = {
336 .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
337 | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
338 | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
339 .health = ND_SMART_NON_CRITICAL_HEALTH,
340 .temperature = 23 * 16,
341 .spares = 75,
342 .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
343 .life_used = 5,
344 .shutdown_state = 0,
345 .vendor_size = 0,
346 };
347
348 if (buf_len < sizeof(*smart))
349 return -EINVAL;
350 memcpy(smart->data, &smart_data, sizeof(smart_data));
351 return 0;
352}
353
354static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
355 unsigned int buf_len)
356{
357 static const struct nd_smart_threshold_payload smart_t_data = {
358 .alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
359 .temperature = 40 * 16,
360 .spares = 5,
361 };
362
363 if (buf_len < sizeof(*smart_t))
364 return -EINVAL;
365 memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
366 return 0;
367}
368
333static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, 369static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
334 struct nvdimm *nvdimm, unsigned int cmd, void *buf, 370 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
335 unsigned int buf_len, int *cmd_rc) 371 unsigned int buf_len, int *cmd_rc)
336{ 372{
337 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 373 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
338 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 374 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
375 unsigned int func = cmd;
339 int i, rc = 0, __cmd_rc; 376 int i, rc = 0, __cmd_rc;
340 377
341 if (!cmd_rc) 378 if (!cmd_rc)
@@ -344,8 +381,23 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
344 381
345 if (nvdimm) { 382 if (nvdimm) {
346 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 383 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
384 unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
347 385
348 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 386 if (!nfit_mem)
387 return -ENOTTY;
388
389 if (cmd == ND_CMD_CALL) {
390 struct nd_cmd_pkg *call_pkg = buf;
391
392 buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
393 buf = (void *) call_pkg->nd_payload;
394 func = call_pkg->nd_command;
395 if (call_pkg->nd_family != nfit_mem->family)
396 return -ENOTTY;
397 }
398
399 if (!test_bit(cmd, &cmd_mask)
400 || !test_bit(func, &nfit_mem->dsm_mask))
349 return -ENOTTY; 401 return -ENOTTY;
350 402
351 /* lookup label space for the given dimm */ 403 /* lookup label space for the given dimm */
@@ -356,7 +408,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
356 if (i >= ARRAY_SIZE(handle)) 408 if (i >= ARRAY_SIZE(handle))
357 return -ENXIO; 409 return -ENXIO;
358 410
359 switch (cmd) { 411 switch (func) {
360 case ND_CMD_GET_CONFIG_SIZE: 412 case ND_CMD_GET_CONFIG_SIZE:
361 rc = nfit_test_cmd_get_config_size(buf, buf_len); 413 rc = nfit_test_cmd_get_config_size(buf, buf_len);
362 break; 414 break;
@@ -368,16 +420,22 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
368 rc = nfit_test_cmd_set_config_data(buf, buf_len, 420 rc = nfit_test_cmd_set_config_data(buf, buf_len,
369 t->label[i]); 421 t->label[i]);
370 break; 422 break;
423 case ND_CMD_SMART:
424 rc = nfit_test_cmd_smart(buf, buf_len);
425 break;
426 case ND_CMD_SMART_THRESHOLD:
427 rc = nfit_test_cmd_smart_threshold(buf, buf_len);
428 break;
371 default: 429 default:
372 return -ENOTTY; 430 return -ENOTTY;
373 } 431 }
374 } else { 432 } else {
375 struct ars_state *ars_state = &t->ars_state; 433 struct ars_state *ars_state = &t->ars_state;
376 434
377 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) 435 if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
378 return -ENOTTY; 436 return -ENOTTY;
379 437
380 switch (cmd) { 438 switch (func) {
381 case ND_CMD_ARS_CAP: 439 case ND_CMD_ARS_CAP:
382 rc = nfit_test_cmd_ars_cap(buf, buf_len); 440 rc = nfit_test_cmd_ars_cap(buf, buf_len);
383 break; 441 break;
@@ -1251,13 +1309,15 @@ static void nfit_test0_setup(struct nfit_test *t)
1251 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1309 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
1252 1310
1253 acpi_desc = &t->acpi_desc; 1311 acpi_desc = &t->acpi_desc;
1254 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 1312 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1255 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1313 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1256 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1314 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1257 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1315 set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en);
1258 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1316 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1259 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1317 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1260 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1318 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1261} 1321}
1262 1322
1263static void nfit_test1_setup(struct nfit_test *t) 1323static void nfit_test1_setup(struct nfit_test *t)
@@ -1315,10 +1375,10 @@ static void nfit_test1_setup(struct nfit_test *t)
1315 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); 1375 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE);
1316 1376
1317 acpi_desc = &t->acpi_desc; 1377 acpi_desc = &t->acpi_desc;
1318 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1378 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1379 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1380 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1321 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1381 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1322} 1382}
1323 1383
1324static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1384static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 604212db9d4b..3b530467148e 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
6 regression1.o regression2.o regression3.o 6 regression1.o regression2.o regression3.o multiorder.o
7 7
8targets: $(TARGETS) 8targets: $(TARGETS)
9 9
@@ -13,7 +13,7 @@ main: $(OFILES)
13clean: 13clean:
14 $(RM) -f $(TARGETS) *.o radix-tree.c 14 $(RM) -f $(TARGETS) *.o radix-tree.c
15 15
16$(OFILES): *.h */*.h 16$(OFILES): *.h */*.h ../../../include/linux/radix-tree.h ../../include/linux/*.h
17 17
18radix-tree.c: ../../../lib/radix-tree.c 18radix-tree.c: ../../../lib/radix-tree.c
19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
diff --git a/tools/testing/radix-tree/generated/autoconf.h b/tools/testing/radix-tree/generated/autoconf.h
new file mode 100644
index 000000000000..ad18cf5a2a3a
--- /dev/null
+++ b/tools/testing/radix-tree/generated/autoconf.h
@@ -0,0 +1,3 @@
1#define CONFIG_RADIX_TREE_MULTIORDER 1
2#define CONFIG_SHMEM 1
3#define CONFIG_SWAP 1
diff --git a/tools/testing/radix-tree/linux/init.h b/tools/testing/radix-tree/linux/init.h
new file mode 100644
index 000000000000..360cabb3c4e7
--- /dev/null
+++ b/tools/testing/radix-tree/linux/init.h
@@ -0,0 +1 @@
/* An empty file stub that allows radix-tree.c to compile. */
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index ae013b0160ac..be98a47b4e1b 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -7,19 +7,28 @@
7#include <stddef.h> 7#include <stddef.h>
8#include <limits.h> 8#include <limits.h>
9 9
10#include "../../include/linux/compiler.h"
11#include "../../../include/linux/kconfig.h"
12
13#define RADIX_TREE_MAP_SHIFT 3
14
10#ifndef NULL 15#ifndef NULL
11#define NULL 0 16#define NULL 0
12#endif 17#endif
13 18
14#define BUG_ON(expr) assert(!(expr)) 19#define BUG_ON(expr) assert(!(expr))
20#define WARN_ON(expr) assert(!(expr))
15#define __init 21#define __init
16#define __must_check 22#define __must_check
17#define panic(expr) 23#define panic(expr)
18#define printk printf 24#define printk printf
19#define __force 25#define __force
20#define likely(c) (c)
21#define unlikely(c) (c)
22#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 26#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
27#define pr_debug printk
28
29#define smp_rmb() barrier()
30#define smp_wmb() barrier()
31#define cpu_relax() barrier()
23 32
24#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 33#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
25 34
@@ -28,6 +37,8 @@
28 (type *)( (char *)__mptr - offsetof(type, member) );}) 37 (type *)( (char *)__mptr - offsetof(type, member) );})
29#define min(a, b) ((a) < (b) ? (a) : (b)) 38#define min(a, b) ((a) < (b) ? (a) : (b))
30 39
40#define cond_resched() sched_yield()
41
31static inline int in_interrupt(void) 42static inline int in_interrupt(void)
32{ 43{
33 return 0; 44 return 0;
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index 57282506c21d..6d5a34770fd4 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -3,7 +3,6 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#define GFP_KERNEL 1
7#define SLAB_HWCACHE_ALIGN 1 6#define SLAB_HWCACHE_ALIGN 1
8#define SLAB_PANIC 2 7#define SLAB_PANIC 2
9#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */ 8#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
diff --git a/tools/testing/radix-tree/linux/types.h b/tools/testing/radix-tree/linux/types.h
index 72a9d85f6c76..faa0b6ff9ca8 100644
--- a/tools/testing/radix-tree/linux/types.h
+++ b/tools/testing/radix-tree/linux/types.h
@@ -1,15 +1,13 @@
1#ifndef _TYPES_H 1#ifndef _TYPES_H
2#define _TYPES_H 2#define _TYPES_H
3 3
4#include "../../include/linux/types.h"
5
4#define __rcu 6#define __rcu
5#define __read_mostly 7#define __read_mostly
6 8
7#define BITS_PER_LONG (sizeof(long) * 8) 9#define BITS_PER_LONG (sizeof(long) * 8)
8 10
9struct list_head {
10 struct list_head *next, *prev;
11};
12
13static inline void INIT_LIST_HEAD(struct list_head *list) 11static inline void INIT_LIST_HEAD(struct list_head *list)
14{ 12{
15 list->next = list; 13 list->next = list;
@@ -22,7 +20,6 @@ typedef struct {
22 20
23#define uninitialized_var(x) x = x 21#define uninitialized_var(x) x = x
24 22
25typedef unsigned gfp_t;
26#include <linux/gfp.h> 23#include <linux/gfp.h>
27 24
28#endif 25#endif
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index 0e83cad27a9f..b7619ff3b552 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -61,11 +61,11 @@ void __big_gang_check(void)
61 } while (!wrapped); 61 } while (!wrapped);
62} 62}
63 63
64void big_gang_check(void) 64void big_gang_check(bool long_run)
65{ 65{
66 int i; 66 int i;
67 67
68 for (i = 0; i < 1000; i++) { 68 for (i = 0; i < (long_run ? 1000 : 3); i++) {
69 __big_gang_check(); 69 __big_gang_check();
70 srand(time(0)); 70 srand(time(0));
71 printf("%d ", i); 71 printf("%d ", i);
@@ -232,10 +232,72 @@ void copy_tag_check(void)
232 item_kill_tree(&tree); 232 item_kill_tree(&tree);
233} 233}
234 234
235static void single_thread_tests(void) 235static void __locate_check(struct radix_tree_root *tree, unsigned long index,
236 unsigned order)
237{
238 struct item *item;
239 unsigned long index2;
240
241 item_insert_order(tree, index, order);
242 item = item_lookup(tree, index);
243 index2 = radix_tree_locate_item(tree, item);
244 if (index != index2) {
245 printf("index %ld order %d inserted; found %ld\n",
246 index, order, index2);
247 abort();
248 }
249}
250
251static void __order_0_locate_check(void)
252{
253 RADIX_TREE(tree, GFP_KERNEL);
254 int i;
255
256 for (i = 0; i < 50; i++)
257 __locate_check(&tree, rand() % INT_MAX, 0);
258
259 item_kill_tree(&tree);
260}
261
262static void locate_check(void)
263{
264 RADIX_TREE(tree, GFP_KERNEL);
265 unsigned order;
266 unsigned long offset, index;
267
268 __order_0_locate_check();
269
270 for (order = 0; order < 20; order++) {
271 for (offset = 0; offset < (1 << (order + 3));
272 offset += (1UL << order)) {
273 for (index = 0; index < (1UL << (order + 5));
274 index += (1UL << order)) {
275 __locate_check(&tree, index + offset, order);
276 }
277 if (radix_tree_locate_item(&tree, &tree) != -1)
278 abort();
279
280 item_kill_tree(&tree);
281 }
282 }
283
284 if (radix_tree_locate_item(&tree, &tree) != -1)
285 abort();
286 __locate_check(&tree, -1, 0);
287 if (radix_tree_locate_item(&tree, &tree) != -1)
288 abort();
289 item_kill_tree(&tree);
290}
291
292static void single_thread_tests(bool long_run)
236{ 293{
237 int i; 294 int i;
238 295
296 printf("starting single_thread_tests: %d allocated\n", nr_allocated);
297 multiorder_checks();
298 printf("after multiorder_check: %d allocated\n", nr_allocated);
299 locate_check();
300 printf("after locate_check: %d allocated\n", nr_allocated);
239 tag_check(); 301 tag_check();
240 printf("after tag_check: %d allocated\n", nr_allocated); 302 printf("after tag_check: %d allocated\n", nr_allocated);
241 gang_check(); 303 gang_check();
@@ -244,9 +306,9 @@ static void single_thread_tests(void)
244 printf("after add_and_check: %d allocated\n", nr_allocated); 306 printf("after add_and_check: %d allocated\n", nr_allocated);
245 dynamic_height_check(); 307 dynamic_height_check();
246 printf("after dynamic_height_check: %d allocated\n", nr_allocated); 308 printf("after dynamic_height_check: %d allocated\n", nr_allocated);
247 big_gang_check(); 309 big_gang_check(long_run);
248 printf("after big_gang_check: %d allocated\n", nr_allocated); 310 printf("after big_gang_check: %d allocated\n", nr_allocated);
249 for (i = 0; i < 2000; i++) { 311 for (i = 0; i < (long_run ? 2000 : 3); i++) {
250 copy_tag_check(); 312 copy_tag_check();
251 printf("%d ", i); 313 printf("%d ", i);
252 fflush(stdout); 314 fflush(stdout);
@@ -254,15 +316,23 @@ static void single_thread_tests(void)
254 printf("after copy_tag_check: %d allocated\n", nr_allocated); 316 printf("after copy_tag_check: %d allocated\n", nr_allocated);
255} 317}
256 318
257int main(void) 319int main(int argc, char **argv)
258{ 320{
321 bool long_run = false;
322 int opt;
323
324 while ((opt = getopt(argc, argv, "l")) != -1) {
325 if (opt == 'l')
326 long_run = true;
327 }
328
259 rcu_register_thread(); 329 rcu_register_thread();
260 radix_tree_init(); 330 radix_tree_init();
261 331
262 regression1_test(); 332 regression1_test();
263 regression2_test(); 333 regression2_test();
264 regression3_test(); 334 regression3_test();
265 single_thread_tests(); 335 single_thread_tests(long_run);
266 336
267 sleep(1); 337 sleep(1);
268 printf("after sleep(1): %d allocated\n", nr_allocated); 338 printf("after sleep(1): %d allocated\n", nr_allocated);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
new file mode 100644
index 000000000000..39d9b9568fe2
--- /dev/null
+++ b/tools/testing/radix-tree/multiorder.c
@@ -0,0 +1,337 @@
1/*
2 * multiorder.c: Multi-order radix tree entry testing
3 * Copyright (c) 2016 Intel Corporation
4 * Author: Ross Zwisler <ross.zwisler@linux.intel.com>
5 * Author: Matthew Wilcox <matthew.r.wilcox@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16#include <linux/radix-tree.h>
17#include <linux/slab.h>
18#include <linux/errno.h>
19
20#include "test.h"
21
22#define for_each_index(i, base, order) \
23 for (i = base; i < base + (1 << order); i++)
24
25static void __multiorder_tag_test(int index, int order)
26{
27 RADIX_TREE(tree, GFP_KERNEL);
28 int base, err, i;
29 unsigned long first = 0;
30
31 /* our canonical entry */
32 base = index & ~((1 << order) - 1);
33
34 printf("Multiorder tag test with index %d, canonical entry %d\n",
35 index, base);
36
37 err = item_insert_order(&tree, index, order);
38 assert(!err);
39
40 /*
41 * Verify we get collisions for covered indices. We try and fail to
42 * insert an exceptional entry so we don't leak memory via
43 * item_insert_order().
44 */
45 for_each_index(i, base, order) {
46 err = __radix_tree_insert(&tree, i, order,
47 (void *)(0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY));
48 assert(err == -EEXIST);
49 }
50
51 for_each_index(i, base, order) {
52 assert(!radix_tree_tag_get(&tree, i, 0));
53 assert(!radix_tree_tag_get(&tree, i, 1));
54 }
55
56 assert(radix_tree_tag_set(&tree, index, 0));
57
58 for_each_index(i, base, order) {
59 assert(radix_tree_tag_get(&tree, i, 0));
60 assert(!radix_tree_tag_get(&tree, i, 1));
61 }
62
63 assert(radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 10, 0, 1) == 1);
64 assert(radix_tree_tag_clear(&tree, index, 0));
65
66 for_each_index(i, base, order) {
67 assert(!radix_tree_tag_get(&tree, i, 0));
68 assert(radix_tree_tag_get(&tree, i, 1));
69 }
70
71 assert(radix_tree_tag_clear(&tree, index, 1));
72
73 assert(!radix_tree_tagged(&tree, 0));
74 assert(!radix_tree_tagged(&tree, 1));
75
76 item_kill_tree(&tree);
77}
78
79static void multiorder_tag_tests(void)
80{
81 /* test multi-order entry for indices 0-7 with no sibling pointers */
82 __multiorder_tag_test(0, 3);
83 __multiorder_tag_test(5, 3);
84
85 /* test multi-order entry for indices 8-15 with no sibling pointers */
86 __multiorder_tag_test(8, 3);
87 __multiorder_tag_test(15, 3);
88
89 /*
90 * Our order 5 entry covers indices 0-31 in a tree with height=2.
91 * This is broken up as follows:
92 * 0-7: canonical entry
93 * 8-15: sibling 1
94 * 16-23: sibling 2
95 * 24-31: sibling 3
96 */
97 __multiorder_tag_test(0, 5);
98 __multiorder_tag_test(29, 5);
99
100 /* same test, but with indices 32-63 */
101 __multiorder_tag_test(32, 5);
102 __multiorder_tag_test(44, 5);
103
104 /*
105 * Our order 8 entry covers indices 0-255 in a tree with height=3.
106 * This is broken up as follows:
107 * 0-63: canonical entry
108 * 64-127: sibling 1
109 * 128-191: sibling 2
110 * 192-255: sibling 3
111 */
112 __multiorder_tag_test(0, 8);
113 __multiorder_tag_test(190, 8);
114
115 /* same test, but with indices 256-511 */
116 __multiorder_tag_test(256, 8);
117 __multiorder_tag_test(300, 8);
118
119 __multiorder_tag_test(0x12345678UL, 8);
120}
121
122static void multiorder_check(unsigned long index, int order)
123{
124 unsigned long i;
125 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order);
127 RADIX_TREE(tree, GFP_KERNEL);
128
129 printf("Multiorder index %ld, order %d\n", index, order);
130
131 assert(item_insert_order(&tree, index, order) == 0);
132
133 for (i = min; i < max; i++) {
134 struct item *item = item_lookup(&tree, i);
135 assert(item != 0);
136 assert(item->index == index);
137 }
138 for (i = 0; i < min; i++)
139 item_check_absent(&tree, i);
140 for (i = max; i < 2*max; i++)
141 item_check_absent(&tree, i);
142 for (i = min; i < max; i++) {
143 static void *entry = (void *)
144 (0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY);
145 assert(radix_tree_insert(&tree, i, entry) == -EEXIST);
146 }
147
148 assert(item_delete(&tree, index) != 0);
149
150 for (i = 0; i < 2*max; i++)
151 item_check_absent(&tree, i);
152}
153
154static void multiorder_shrink(unsigned long index, int order)
155{
156 unsigned long i;
157 unsigned long max = 1 << order;
158 RADIX_TREE(tree, GFP_KERNEL);
159 struct radix_tree_node *node;
160
161 printf("Multiorder shrink index %ld, order %d\n", index, order);
162
163 assert(item_insert_order(&tree, 0, order) == 0);
164
165 node = tree.rnode;
166
167 assert(item_insert(&tree, index) == 0);
168 assert(node != tree.rnode);
169
170 assert(item_delete(&tree, index) != 0);
171 assert(node == tree.rnode);
172
173 for (i = 0; i < max; i++) {
174 struct item *item = item_lookup(&tree, i);
175 assert(item != 0);
176 assert(item->index == 0);
177 }
178 for (i = max; i < 2*max; i++)
179 item_check_absent(&tree, i);
180
181 if (!item_delete(&tree, 0)) {
182 printf("failed to delete index %ld (order %d)\n", index, order); abort();
183 }
184
185 for (i = 0; i < 2*max; i++)
186 item_check_absent(&tree, i);
187}
188
189static void multiorder_insert_bug(void)
190{
191 RADIX_TREE(tree, GFP_KERNEL);
192
193 item_insert(&tree, 0);
194 radix_tree_tag_set(&tree, 0, 0);
195 item_insert_order(&tree, 3 << 6, 6);
196
197 item_kill_tree(&tree);
198}
199
200void multiorder_iteration(void)
201{
202 RADIX_TREE(tree, GFP_KERNEL);
203 struct radix_tree_iter iter;
204 void **slot;
205 int i, j, err;
206
207 printf("Multiorder iteration test\n");
208
209#define NUM_ENTRIES 11
210 int index[NUM_ENTRIES] = {0, 2, 4, 8, 16, 32, 34, 36, 64, 72, 128};
211 int order[NUM_ENTRIES] = {1, 1, 2, 3, 4, 1, 0, 1, 3, 0, 7};
212
213 for (i = 0; i < NUM_ENTRIES; i++) {
214 err = item_insert_order(&tree, index[i], order[i]);
215 assert(!err);
216 }
217
218 for (j = 0; j < 256; j++) {
219 for (i = 0; i < NUM_ENTRIES; i++)
220 if (j <= (index[i] | ((1 << order[i]) - 1)))
221 break;
222
223 radix_tree_for_each_slot(slot, &tree, &iter, j) {
224 int height = order[i] / RADIX_TREE_MAP_SHIFT;
225 int shift = height * RADIX_TREE_MAP_SHIFT;
226 int mask = (1 << order[i]) - 1;
227
228 assert(iter.index >= (index[i] &~ mask));
229 assert(iter.index <= (index[i] | mask));
230 assert(iter.shift == shift);
231 i++;
232 }
233 }
234
235 item_kill_tree(&tree);
236}
237
238void multiorder_tagged_iteration(void)
239{
240 RADIX_TREE(tree, GFP_KERNEL);
241 struct radix_tree_iter iter;
242 void **slot;
243 unsigned long first = 0;
244 int i, j;
245
246 printf("Multiorder tagged iteration test\n");
247
248#define MT_NUM_ENTRIES 9
249 int index[MT_NUM_ENTRIES] = {0, 2, 4, 16, 32, 40, 64, 72, 128};
250 int order[MT_NUM_ENTRIES] = {1, 0, 2, 4, 3, 1, 3, 0, 7};
251
252#define TAG_ENTRIES 7
253 int tag_index[TAG_ENTRIES] = {0, 4, 16, 40, 64, 72, 128};
254
255 for (i = 0; i < MT_NUM_ENTRIES; i++)
256 assert(!item_insert_order(&tree, index[i], order[i]));
257
258 assert(!radix_tree_tagged(&tree, 1));
259
260 for (i = 0; i < TAG_ENTRIES; i++)
261 assert(radix_tree_tag_set(&tree, tag_index[i], 1));
262
263 for (j = 0; j < 256; j++) {
264 int mask, k;
265
266 for (i = 0; i < TAG_ENTRIES; i++) {
267 for (k = i; index[k] < tag_index[i]; k++)
268 ;
269 if (j <= (index[k] | ((1 << order[k]) - 1)))
270 break;
271 }
272
273 radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) {
274 for (k = i; index[k] < tag_index[i]; k++)
275 ;
276 mask = (1 << order[k]) - 1;
277
278 assert(iter.index >= (tag_index[i] &~ mask));
279 assert(iter.index <= (tag_index[i] | mask));
280 i++;
281 }
282 }
283
284 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
285 MT_NUM_ENTRIES, 1, 2);
286
287 for (j = 0; j < 256; j++) {
288 int mask, k;
289
290 for (i = 0; i < TAG_ENTRIES; i++) {
291 for (k = i; index[k] < tag_index[i]; k++)
292 ;
293 if (j <= (index[k] | ((1 << order[k]) - 1)))
294 break;
295 }
296
297 radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) {
298 for (k = i; index[k] < tag_index[i]; k++)
299 ;
300 mask = (1 << order[k]) - 1;
301
302 assert(iter.index >= (tag_index[i] &~ mask));
303 assert(iter.index <= (tag_index[i] | mask));
304 i++;
305 }
306 }
307
308 first = 1;
309 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
310 MT_NUM_ENTRIES, 1, 0);
311 i = 0;
312 radix_tree_for_each_tagged(slot, &tree, &iter, 0, 0) {
313 assert(iter.index == tag_index[i]);
314 i++;
315 }
316
317 item_kill_tree(&tree);
318}
319
320void multiorder_checks(void)
321{
322 int i;
323
324 for (i = 0; i < 20; i++) {
325 multiorder_check(200, i);
326 multiorder_check(0, i);
327 multiorder_check((1UL << i) + 1, i);
328 }
329
330 for (i = 0; i < 15; i++)
331 multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i);
332
333 multiorder_insert_bug();
334 multiorder_tag_tests();
335 multiorder_iteration();
336 multiorder_tagged_iteration();
337}
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index 5d2fa28cdca3..63bf347aaf33 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -51,13 +51,6 @@
51 51
52#include "regression.h" 52#include "regression.h"
53 53
54#ifdef __KERNEL__
55#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)
56#else
57#define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */
58#endif
59
60#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
61#define PAGECACHE_TAG_DIRTY 0 54#define PAGECACHE_TAG_DIRTY 0
62#define PAGECACHE_TAG_WRITEBACK 1 55#define PAGECACHE_TAG_WRITEBACK 1
63#define PAGECACHE_TAG_TOWRITE 2 56#define PAGECACHE_TAG_TOWRITE 2
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index 83136be552a0..b7447ceb75e9 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -12,6 +12,7 @@
12static void 12static void
13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag) 13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
14{ 14{
15 unsigned long first = 0;
15 int ret; 16 int ret;
16 17
17 item_check_absent(tree, index); 18 item_check_absent(tree, index);
@@ -22,6 +23,10 @@ __simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
22 item_tag_set(tree, index, tag); 23 item_tag_set(tree, index, tag);
23 ret = item_tag_get(tree, index, tag); 24 ret = item_tag_get(tree, index, tag);
24 assert(ret != 0); 25 assert(ret != 0);
26 ret = radix_tree_range_tag_if_tagged(tree, &first, ~0UL, 10, tag, !tag);
27 assert(ret == 1);
28 ret = item_tag_get(tree, index, !tag);
29 assert(ret != 0);
25 ret = item_delete(tree, index); 30 ret = item_delete(tree, index);
26 assert(ret != 0); 31 assert(ret != 0);
27 item_insert(tree, index); 32 item_insert(tree, index);
@@ -304,6 +309,7 @@ static void single_check(void)
304 struct item *items[BATCH]; 309 struct item *items[BATCH];
305 RADIX_TREE(tree, GFP_KERNEL); 310 RADIX_TREE(tree, GFP_KERNEL);
306 int ret; 311 int ret;
312 unsigned long first = 0;
307 313
308 item_insert(&tree, 0); 314 item_insert(&tree, 0);
309 item_tag_set(&tree, 0, 0); 315 item_tag_set(&tree, 0, 0);
@@ -313,6 +319,10 @@ static void single_check(void)
313 assert(ret == 0); 319 assert(ret == 0);
314 verify_tag_consistency(&tree, 0); 320 verify_tag_consistency(&tree, 0);
315 verify_tag_consistency(&tree, 1); 321 verify_tag_consistency(&tree, 1);
322 ret = radix_tree_range_tag_if_tagged(&tree, &first, 10, 10, 0, 1);
323 assert(ret == 1);
324 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 1);
325 assert(ret == 1);
316 item_kill_tree(&tree); 326 item_kill_tree(&tree);
317} 327}
318 328
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 2bebf34cdc27..a6e8099eaf4f 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -24,14 +24,21 @@ int item_tag_get(struct radix_tree_root *root, unsigned long index, int tag)
24 return radix_tree_tag_get(root, index, tag); 24 return radix_tree_tag_get(root, index, tag);
25} 25}
26 26
27int __item_insert(struct radix_tree_root *root, struct item *item) 27int __item_insert(struct radix_tree_root *root, struct item *item,
28 unsigned order)
28{ 29{
29 return radix_tree_insert(root, item->index, item); 30 return __radix_tree_insert(root, item->index, order, item);
30} 31}
31 32
32int item_insert(struct radix_tree_root *root, unsigned long index) 33int item_insert(struct radix_tree_root *root, unsigned long index)
33{ 34{
34 return __item_insert(root, item_create(index)); 35 return __item_insert(root, item_create(index), 0);
36}
37
38int item_insert_order(struct radix_tree_root *root, unsigned long index,
39 unsigned order)
40{
41 return __item_insert(root, item_create(index), order);
35} 42}
36 43
37int item_delete(struct radix_tree_root *root, unsigned long index) 44int item_delete(struct radix_tree_root *root, unsigned long index)
@@ -136,13 +143,13 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
136} 143}
137 144
138static int verify_node(struct radix_tree_node *slot, unsigned int tag, 145static int verify_node(struct radix_tree_node *slot, unsigned int tag,
139 unsigned int height, int tagged) 146 int tagged)
140{ 147{
141 int anyset = 0; 148 int anyset = 0;
142 int i; 149 int i;
143 int j; 150 int j;
144 151
145 slot = indirect_to_ptr(slot); 152 slot = entry_to_node(slot);
146 153
147 /* Verify consistency at this level */ 154 /* Verify consistency at this level */
148 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) { 155 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) {
@@ -152,7 +159,8 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
152 } 159 }
153 } 160 }
154 if (tagged != anyset) { 161 if (tagged != anyset) {
155 printf("tag: %u, height %u, tagged: %d, anyset: %d\n", tag, height, tagged, anyset); 162 printf("tag: %u, shift %u, tagged: %d, anyset: %d\n",
163 tag, slot->shift, tagged, anyset);
156 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 164 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
157 printf("tag %d: ", j); 165 printf("tag %d: ", j);
158 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) 166 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++)
@@ -164,10 +172,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
164 assert(tagged == anyset); 172 assert(tagged == anyset);
165 173
166 /* Go for next level */ 174 /* Go for next level */
167 if (height > 1) { 175 if (slot->shift > 0) {
168 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) 176 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++)
169 if (slot->slots[i]) 177 if (slot->slots[i])
170 if (verify_node(slot->slots[i], tag, height - 1, 178 if (verify_node(slot->slots[i], tag,
171 !!test_bit(i, slot->tags[tag]))) { 179 !!test_bit(i, slot->tags[tag]))) {
172 printf("Failure at off %d\n", i); 180 printf("Failure at off %d\n", i);
173 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 181 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
@@ -184,9 +192,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
184 192
185void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag) 193void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)
186{ 194{
187 if (!root->height) 195 struct radix_tree_node *node = root->rnode;
196 if (!radix_tree_is_internal_node(node))
188 return; 197 return;
189 verify_node(root->rnode, tag, root->height, !!root_tag_get(root, tag)); 198 verify_node(node, tag, !!root_tag_get(root, tag));
190} 199}
191 200
192void item_kill_tree(struct radix_tree_root *root) 201void item_kill_tree(struct radix_tree_root *root)
@@ -211,9 +220,19 @@ void item_kill_tree(struct radix_tree_root *root)
211 220
212void tree_verify_min_height(struct radix_tree_root *root, int maxindex) 221void tree_verify_min_height(struct radix_tree_root *root, int maxindex)
213{ 222{
214 assert(radix_tree_maxindex(root->height) >= maxindex); 223 unsigned shift;
215 if (root->height > 1) 224 struct radix_tree_node *node = root->rnode;
216 assert(radix_tree_maxindex(root->height-1) < maxindex); 225 if (!radix_tree_is_internal_node(node)) {
217 else if (root->height == 1) 226 assert(maxindex == 0);
218 assert(radix_tree_maxindex(root->height-1) <= maxindex); 227 return;
228 }
229
230 node = entry_to_node(node);
231 assert(maxindex <= node_maxindex(node));
232
233 shift = node->shift;
234 if (shift > 0)
235 assert(maxindex > shift_maxindex(shift - RADIX_TREE_MAP_SHIFT));
236 else
237 assert(maxindex > 0);
219} 238}
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 4e1d95faaa94..e85131369723 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -8,8 +8,11 @@ struct item {
8}; 8};
9 9
10struct item *item_create(unsigned long index); 10struct item *item_create(unsigned long index);
11int __item_insert(struct radix_tree_root *root, struct item *item); 11int __item_insert(struct radix_tree_root *root, struct item *item,
12 unsigned order);
12int item_insert(struct radix_tree_root *root, unsigned long index); 13int item_insert(struct radix_tree_root *root, unsigned long index);
14int item_insert_order(struct radix_tree_root *root, unsigned long index,
15 unsigned order);
13int item_delete(struct radix_tree_root *root, unsigned long index); 16int item_delete(struct radix_tree_root *root, unsigned long index);
14struct item *item_lookup(struct radix_tree_root *root, unsigned long index); 17struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
15 18
@@ -23,6 +26,7 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
23void item_kill_tree(struct radix_tree_root *root); 26void item_kill_tree(struct radix_tree_root *root);
24 27
25void tag_check(void); 28void tag_check(void);
29void multiorder_checks(void);
26 30
27struct item * 31struct item *
28item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 32item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
@@ -35,6 +39,7 @@ void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag);
35extern int nr_allocated; 39extern int nr_allocated;
36 40
37/* Normally private parts of lib/radix-tree.c */ 41/* Normally private parts of lib/radix-tree.c */
38void *indirect_to_ptr(void *ptr); 42void radix_tree_dump(struct radix_tree_root *root);
39int root_tag_get(struct radix_tree_root *root, unsigned int tag); 43int root_tag_get(struct radix_tree_root *root, unsigned int tag);
40unsigned long radix_tree_maxindex(unsigned int height); 44unsigned long node_maxindex(struct radix_tree_node *);
45unsigned long shift_maxindex(unsigned int shift);
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index da48812ab95e..4c6a0bf8ba79 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -88,7 +88,12 @@ parse_opts() { # opts
88 88
89# Parameters 89# Parameters
90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` 90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
91TRACING_DIR=$DEBUGFS_DIR/tracing 91if [ -z "$DEBUGFS_DIR" ]; then
92 TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
93else
94 TRACING_DIR=$DEBUGFS_DIR/tracing
95fi
96
92TOP_DIR=`absdir $0` 97TOP_DIR=`absdir $0`
93TEST_DIR=$TOP_DIR/test.d 98TEST_DIR=$TOP_DIR/test.d
94TEST_CASES=`find_testcases $TEST_DIR` 99TEST_CASES=`find_testcases $TEST_DIR`
@@ -102,7 +107,7 @@ parse_opts $*
102[ $DEBUG -ne 0 ] && set -x 107[ $DEBUG -ne 0 ] && set -x
103 108
104# Verify parameters 109# Verify parameters
105if [ -z "$DEBUGFS_DIR" -o ! -d "$TRACING_DIR" ]; then 110if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
106 errexit "No ftrace directory found" 111 errexit "No ftrace directory found"
107fi 112fi
108 113
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
new file mode 100644
index 000000000000..d4ab27b522f8
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
@@ -0,0 +1,72 @@
1#!/bin/sh
2# description: event tracing - restricts events based on pid
3
4do_reset() {
5 echo > set_event
6 echo > set_event_pid
7 echo 0 > options/event-fork
8 clear_trace
9}
10
11fail() { #msg
12 do_reset
13 echo $1
14 exit $FAIL
15}
16
17yield() {
18 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
19}
20
21if [ ! -f set_event -o ! -d events/sched ]; then
22 echo "event tracing is not supported"
23 exit_unsupported
24fi
25
26if [ ! -f set_event_pid ]; then
27 echo "event pid filtering is not supported"
28 exit_unsupported
29fi
30
31reset_tracer
32do_reset
33
34echo 1 > events/sched/sched_switch/enable
35
36yield
37
38count=`cat trace | grep sched_switch | wc -l`
39if [ $count -eq 0 ]; then
40 fail "sched_switch events are not recorded"
41fi
42
43do_reset
44
45read mypid rest < /proc/self/stat
46
47echo $mypid > set_event_pid
48echo 'sched:sched_switch' > set_event
49
50yield
51
52count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
53if [ $count -ne 0 ]; then
54 fail "sched_switch events from other task are recorded"
55fi
56
57do_reset
58
59echo $mypid > set_event_pid
60echo 1 > options/event-fork
61echo 1 > events/sched/sched_switch/enable
62
63yield
64
65count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
66if [ $count -eq 0 ]; then
67 fail "sched_switch events from other task are not recorded"
68fi
69
70do_reset
71
72exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index 5d8cd06d920f..c37262f6c269 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -14,3 +14,12 @@ enable_tracing() { # start trace recording
14reset_tracer() { # reset the current tracer 14reset_tracer() { # reset the current tracer
15 echo nop > current_tracer 15 echo nop > current_tracer
16} 16}
17
18reset_trigger() { # reset all current setting triggers
19 grep -v ^# events/*/*/trigger |
20 while read line; do
21 cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "`
22 echo "!$cmd" > `echo $line | cut -f1 -d:`
23 done
24}
25
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
new file mode 100644
index 000000000000..4c5a061a5b4e
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
@@ -0,0 +1,138 @@
1#!/bin/sh
2# description: Test creation and deletion of trace instances while setting an event
3
4if [ ! -d instances ] ; then
5 echo "no instance directory with this kernel"
6 exit_unsupported;
7fi
8
9fail() { # mesg
10 rmdir foo 2>/dev/null
11 echo $1
12 set -e
13 exit $FAIL
14}
15
16cd instances
17
18# we don't want to fail on error
19set +e
20
21mkdir x
22rmdir x
23result=$?
24
25if [ $result -ne 0 ]; then
26 echo "instance rmdir not supported"
27 exit_unsupported
28fi
29
30instance_slam() {
31 while :; do
32 mkdir foo 2> /dev/null
33 rmdir foo 2> /dev/null
34 done
35}
36
37instance_read() {
38 while :; do
39 cat foo/trace 1> /dev/null 2>&1
40 done
41}
42
43instance_set() {
44 while :; do
45 echo 1 > foo/events/sched/sched_switch
46 done 2> /dev/null
47}
48
49instance_slam &
50p1=$!
51echo $p1
52
53instance_set &
54p2=$!
55echo $p2
56
57instance_read &
58p3=$!
59echo $p3
60
61sleep 1
62
63kill -1 $p3
64kill -1 $p2
65kill -1 $p1
66
67echo "Wait for processes to finish"
68wait $p1 $p2 $p3
69echo "all processes finished, wait for cleanup"
70sleep 1
71
72mkdir foo
73ls foo > /dev/null
74rmdir foo
75if [ -d foo ]; then
76 fail "foo still exists"
77fi
78exit 0
79
80
81
82
83instance_slam() {
84 while :; do
85 mkdir x
86 mkdir y
87 mkdir z
88 rmdir x
89 rmdir y
90 rmdir z
91 done 2>/dev/null
92}
93
94instance_slam &
95p1=$!
96echo $p1
97
98instance_slam &
99p2=$!
100echo $p2
101
102instance_slam &
103p3=$!
104echo $p3
105
106instance_slam &
107p4=$!
108echo $p4
109
110instance_slam &
111p5=$!
112echo $p5
113
114ls -lR >/dev/null
115sleep 1
116
117kill -1 $p1
118kill -1 $p2
119kill -1 $p3
120kill -1 $p4
121kill -1 $p5
122
123echo "Wait for processes to finish"
124wait $p1 $p2 $p3 $p4 $p5
125echo "all processes finished, wait for cleanup"
126
127mkdir x y z
128ls x y z
129rmdir x y z
130for d in x y z; do
131 if [ -d $d ]; then
132 fail "instance $d still exists"
133 fi
134done
135
136set -e
137
138exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
new file mode 100644
index 000000000000..1a9445021bf1
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
@@ -0,0 +1,64 @@
1#!/bin/sh
2# description: event trigger - test event enable/disable trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep enable_event events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "event enable/disable trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test enable_event trigger"
36echo 0 > events/sched/sched_switch/enable
37echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
38( echo "forked")
39if [ `cat events/sched/sched_switch/enable` != '1*' ]; then
40 fail "enable_event trigger on sched_process_fork did not work"
41fi
42
43reset_trigger
44
45echo "Test disable_event trigger"
46echo 1 > events/sched/sched_switch/enable
47echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
48( echo "forked")
49if [ `cat events/sched/sched_switch/enable` != '0*' ]; then
50 fail "disable_event trigger on sched_process_fork did not work"
51fi
52
53reset_trigger
54
55echo "Test semantic error for event enable/disable trigger"
56! echo 'enable_event:nogroup:noevent' > events/sched/sched_process_fork/trigger
57! echo 'disable_event+1' > events/sched/sched_process_fork/trigger
58echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
59! echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
60! echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
61
62do_reset
63
64exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
new file mode 100644
index 000000000000..514e466e198b
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
@@ -0,0 +1,59 @@
1#!/bin/sh
2# description: event trigger - test trigger filter
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test trigger filter"
30echo 1 > tracing_on
31echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 1 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test semantic error for trigger filter"
40! echo 'traceoff if a' > events/sched/sched_process_fork/trigger
41! echo 'traceoff if common_pid=0' > events/sched/sched_process_fork/trigger
42! echo 'traceoff if common_pid==b' > events/sched/sched_process_fork/trigger
43echo 'traceoff if common_pid == 0' > events/sched/sched_process_fork/trigger
44echo '!traceoff' > events/sched/sched_process_fork/trigger
45! echo 'traceoff if common_pid == child_pid' > events/sched/sched_process_fork/trigger
46echo 'traceoff if common_pid <= 0' > events/sched/sched_process_fork/trigger
47echo '!traceoff' > events/sched/sched_process_fork/trigger
48echo 'traceoff if common_pid >= 0' > events/sched/sched_process_fork/trigger
49echo '!traceoff' > events/sched/sched_process_fork/trigger
50echo 'traceoff if parent_pid >= 0 && child_pid >= 0' > events/sched/sched_process_fork/trigger
51echo '!traceoff' > events/sched/sched_process_fork/trigger
52echo 'traceoff if parent_pid >= 0 || child_pid >= 0' > events/sched/sched_process_fork/trigger
53echo '!traceoff' > events/sched/sched_process_fork/trigger
54
55
56
57do_reset
58
59exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
new file mode 100644
index 000000000000..c2b61c4fda11
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
@@ -0,0 +1,75 @@
1#!/bin/sh
2# description: event trigger - test histogram modifiers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram with execname modifier"
36
37echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39COMM=`cat /proc/$$/comm`
40grep "common_pid: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
41 fail "execname modifier on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test histogram with hex modifier"
46
47echo 'hist:keys=parent_pid.hex' > events/sched/sched_process_fork/trigger
48for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
49# Note that $$ is the parent pid. $PID is current PID.
50HEX=`printf %x $PID`
51grep "parent_pid: $HEX" events/sched/sched_process_fork/hist > /dev/null || \
52 fail "hex modifier on sched_process_fork did not work"
53
54reset_trigger
55
56echo "Test histogram with syscall modifier"
57
58echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger
59for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
60grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \
61 fail "syscall modifier on raw_syscalls/sys_exit did not work"
62
63
64reset_trigger
65
66echo "Test histgram with log2 modifier"
67
68echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger
69for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
70grep 'bytes_req: ~ 2^[0-9]*' events/kmem/kmalloc/hist > /dev/null || \
71 fail "log2 modifier on kmem/kmalloc did not work"
72
73do_reset
74
75exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
new file mode 100644
index 000000000000..b2902d42a537
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
@@ -0,0 +1,83 @@
1#!/bin/sh
2# description: event trigger - test histogram trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram basic tigger"
36
37echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
40 fail "hist trigger on sched_process_fork did not work"
41grep child events/sched/sched_process_fork/hist > /dev/null || \
42 fail "hist trigger on sched_process_fork did not work"
43
44reset_trigger
45
46echo "Test histogram with compound keys"
47
48echo 'hist:keys=parent_pid,child_pid' > events/sched/sched_process_fork/trigger
49for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
50grep '^{ parent_pid:.*, child_pid:.*}' events/sched/sched_process_fork/hist > /dev/null || \
51 fail "compound keys on sched_process_fork did not work"
52
53reset_trigger
54
55echo "Test histogram with string key"
56
57echo 'hist:keys=parent_comm' > events/sched/sched_process_fork/trigger
58for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
59COMM=`cat /proc/$$/comm`
60grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
61 fail "string key on sched_process_fork did not work"
62
63reset_trigger
64
65echo "Test histogram with sort key"
66
67echo 'hist:keys=parent_pid,child_pid:sort=child_pid.ascending' > events/sched/sched_process_fork/trigger
68for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
69
70check_inc() {
71 while [ $# -gt 1 ]; do
72 [ $1 -gt $2 ] && return 1
73 shift 1
74 done
75 return 0
76}
77check_inc `grep -o "child_pid:[[:space:]]*[[:digit:]]*" \
78 events/sched/sched_process_fork/hist | cut -d: -f2 ` ||
79 fail "sort param on sched_process_fork did not work"
80
81do_reset
82
83exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
new file mode 100644
index 000000000000..03c4a46561fc
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
@@ -0,0 +1,73 @@
1#!/bin/sh
2# description: event trigger - test multiple histogram triggers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35reset_trigger
36
37echo "Test histogram multiple tiggers"
38
39echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
40echo 'hist:keys=parent_comm:vals=child_pid' >> events/sched/sched_process_fork/trigger
41for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
42grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
43 fail "hist trigger on sched_process_fork did not work"
44grep child events/sched/sched_process_fork/hist > /dev/null || \
45 fail "hist trigger on sched_process_fork did not work"
46COMM=`cat /proc/$$/comm`
47grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
48 fail "string key on sched_process_fork did not work"
49
50reset_trigger
51
52echo "Test histogram with its name"
53
54echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_fork/trigger
55for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
56grep test_hist events/sched/sched_process_fork/hist > /dev/null || \
57 fail "named event on sched_process_fork did not work"
58
59echo "Test same named histogram on different events"
60
61echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_exit/trigger
62for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
63grep test_hist events/sched/sched_process_exit/hist > /dev/null || \
64 fail "named event on sched_process_fork did not work"
65
66diffs=`diff events/sched/sched_process_exit/hist events/sched/sched_process_fork/hist | wc -l`
67test $diffs -eq 0 || fail "Same name histograms are not same"
68
69reset_trigger
70
71do_reset
72
73exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
new file mode 100644
index 000000000000..f84b80d551a2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
@@ -0,0 +1,56 @@
1#!/bin/sh
2# description: event trigger - test snapshot-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep snapshot events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "snapshot trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test snapshot tigger"
36echo 0 > snapshot
37echo 1 > events/sched/sched_process_fork/enable
38( echo "forked")
39echo 'snapshot:1' > events/sched/sched_process_fork/trigger
40( echo "forked")
41grep sched_process_fork snapshot > /dev/null || \
42 fail "snapshot trigger on sched_process_fork did not work"
43
44reset_trigger
45echo 0 > snapshot
46echo 0 > events/sched/sched_process_fork/enable
47
48echo "Test snapshot semantic errors"
49
50! echo "snapshot+1" > events/sched/sched_process_fork/trigger
51echo "snapshot" > events/sched/sched_process_fork/trigger
52! echo "snapshot" > events/sched/sched_process_fork/trigger
53
54do_reset
55
56exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
new file mode 100644
index 000000000000..9fa23b085def
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
@@ -0,0 +1,53 @@
1#!/bin/sh
2# description: event trigger - test stacktrace-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "stacktrace trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test stacktrace tigger"
36echo 0 > trace
37echo 0 > options/stacktrace
38echo 'stacktrace' > events/sched/sched_process_fork/trigger
39( echo "forked")
40grep "<stack trace>" trace > /dev/null || \
41 fail "stacktrace trigger on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test stacktrace semantic errors"
46
47! echo "stacktrace:foo" > events/sched/sched_process_fork/trigger
48echo "stacktrace" > events/sched/sched_process_fork/trigger
49! echo "stacktrace" > events/sched/sched_process_fork/trigger
50
51do_reset
52
53exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
new file mode 100644
index 000000000000..87648e5f987c
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
@@ -0,0 +1,58 @@
1#!/bin/sh
2# description: event trigger - test traceon/off trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test traceoff trigger"
30echo 1 > tracing_on
31echo 'traceoff' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 0 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test traceon trigger"
40echo 0 > tracing_on
41echo 'traceon' > events/sched/sched_process_fork/trigger
42( echo "forked")
43if [ `cat tracing_on` -ne 1 ]; then
44 fail "traceoff trigger on sched_process_fork did not work"
45fi
46
47reset_trigger
48
49echo "Test semantic error for traceoff/on trigger"
50! echo 'traceoff:badparam' > events/sched/sched_process_fork/trigger
51! echo 'traceoff+0' > events/sched/sched_process_fork/trigger
52echo 'traceon' > events/sched/sched_process_fork/trigger
53! echo 'traceon' > events/sched/sched_process_fork/trigger
54! echo 'traceoff' > events/sched/sched_process_fork/trigger
55
56do_reset
57
58exit 0
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
index bdaf37e92684..7868c106b8b1 100755
--- a/tools/testing/selftests/intel_pstate/run.sh
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -32,7 +32,7 @@ EVALUATE_ONLY=0
32max_cpus=$(($(nproc)-1)) 32max_cpus=$(($(nproc)-1))
33 33
34# compile programs 34# compile programs
35gcc -o aperf aperf.c -lm 35gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1 36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm 37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1 38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c
index 96ba386b1b7b..4a8217448f20 100644
--- a/tools/testing/selftests/net/reuseport_bpf.c
+++ b/tools/testing/selftests/net/reuseport_bpf.c
@@ -111,9 +111,9 @@ static void attach_ebpf(int fd, uint16_t mod)
111 memset(&attr, 0, sizeof(attr)); 111 memset(&attr, 0, sizeof(attr));
112 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 112 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
113 attr.insn_cnt = ARRAY_SIZE(prog); 113 attr.insn_cnt = ARRAY_SIZE(prog);
114 attr.insns = (uint64_t)prog; 114 attr.insns = (unsigned long) &prog;
115 attr.license = (uint64_t)bpf_license; 115 attr.license = (unsigned long) &bpf_license;
116 attr.log_buf = (uint64_t)bpf_log_buf; 116 attr.log_buf = (unsigned long) &bpf_log_buf;
117 attr.log_size = sizeof(bpf_log_buf); 117 attr.log_size = sizeof(bpf_log_buf);
118 attr.log_level = 1; 118 attr.log_level = 1;
119 attr.kern_version = 0; 119 attr.kern_version = 0;
@@ -351,8 +351,8 @@ static void test_filter_no_reuseport(const struct test_params p)
351 memset(&eprog, 0, sizeof(eprog)); 351 memset(&eprog, 0, sizeof(eprog));
352 eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 352 eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
353 eprog.insn_cnt = ARRAY_SIZE(ecode); 353 eprog.insn_cnt = ARRAY_SIZE(ecode);
354 eprog.insns = (uint64_t)ecode; 354 eprog.insns = (unsigned long) &ecode;
355 eprog.license = (uint64_t)bpf_license; 355 eprog.license = (unsigned long) &bpf_license;
356 eprog.kern_version = 0; 356 eprog.kern_version = 0;
357 357
358 memset(&cprog, 0, sizeof(cprog)); 358 memset(&cprog, 0, sizeof(cprog));
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index b08f77cbe31b..4ca83fe80654 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -14,6 +14,7 @@ export CFLAGS
14 14
15SUB_DIRS = benchmarks \ 15SUB_DIRS = benchmarks \
16 copyloops \ 16 copyloops \
17 context_switch \
17 dscr \ 18 dscr \
18 mm \ 19 mm \
19 pmu \ 20 pmu \
diff --git a/tools/testing/selftests/powerpc/context_switch/.gitignore b/tools/testing/selftests/powerpc/context_switch/.gitignore
new file mode 100644
index 000000000000..c1431af7b51c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/.gitignore
@@ -0,0 +1 @@
cp_abort
diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile b/tools/testing/selftests/powerpc/context_switch/Makefile
new file mode 100644
index 000000000000..e164d1466466
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/Makefile
@@ -0,0 +1,10 @@
1TEST_PROGS := cp_abort
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c
6
7include ../../lib.mk
8
9clean:
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/context_switch/cp_abort.c b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
new file mode 100644
index 000000000000..5a5b55afda0e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
@@ -0,0 +1,110 @@
1/*
2 * Adapted from Anton Blanchard's context switch microbenchmark.
3 *
4 * Copyright 2009, Anton Blanchard, IBM Corporation.
5 * Copyright 2016, Mikey Neuling, Chris Smart, IBM Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * This program tests the copy paste abort functionality of a P9
13 * (or later) by setting up two processes on the same CPU, one
14 * which executes the copy instruction and the other which
15 * executes paste.
16 *
17 * The paste instruction should never succeed, as the cp_abort
18 * instruction is called by the kernel during a context switch.
19 *
20 */
21
22#define _GNU_SOURCE
23
24#include <stdio.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include "utils.h"
28#include <sched.h>
29
30#define READ_FD 0
31#define WRITE_FD 1
32
33#define NUM_LOOPS 1000
34
35/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */
36#define PASTE(RA, RB, L, RC) \
37 .long (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31))
38
39int paste(void *i)
40{
41 int cr;
42
43 asm volatile(str(PASTE(0, %1, 1, 1))";"
44 "mfcr %0;"
45 : "=r" (cr)
46 : "b" (i)
47 : "memory"
48 );
49 return cr;
50}
51
52/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */
53#define COPY(RA, RB, L) \
54 .long (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10))
55
56void copy(void *i)
57{
58 asm volatile(str(COPY(0, %0, 1))";"
59 :
60 : "b" (i)
61 : "memory"
62 );
63}
64
65int test_cp_abort(void)
66{
67 /* 128 bytes for a full cache line */
68 char buf[128] __cacheline_aligned;
69 cpu_set_t cpuset;
70 int fd1[2], fd2[2], pid;
71 char c;
72
73 /* only run this test on a P9 or later */
74 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
75
76 /*
77 * Run both processes on the same CPU, so that copy is more likely
78 * to leak into a paste.
79 */
80 CPU_ZERO(&cpuset);
81 CPU_SET(pick_online_cpu(), &cpuset);
82 FAIL_IF(sched_setaffinity(0, sizeof(cpuset), &cpuset));
83
84 FAIL_IF(pipe(fd1) || pipe(fd2));
85
86 pid = fork();
87 FAIL_IF(pid < 0);
88
89 if (!pid) {
90 for (int i = 0; i < NUM_LOOPS; i++) {
91 FAIL_IF((write(fd1[WRITE_FD], &c, 1)) != 1);
92 FAIL_IF((read(fd2[READ_FD], &c, 1)) != 1);
93 /* A paste succeeds if CR0 EQ bit is set */
94 FAIL_IF(paste(buf) & 0x20000000);
95 }
96 } else {
97 for (int i = 0; i < NUM_LOOPS; i++) {
98 FAIL_IF((read(fd1[READ_FD], &c, 1)) != 1);
99 copy(buf);
100 FAIL_IF((write(fd2[WRITE_FD], &c, 1) != 1));
101 }
102 }
103 return 0;
104
105}
106
107int main(int argc, char *argv[])
108{
109 return test_harness(test_cp_abort, "cp_abort");
110}
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c
index 440180ff8089..35ade7406dcd 100644
--- a/tools/testing/selftests/powerpc/mm/subpage_prot.c
+++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c
@@ -73,7 +73,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
73 want_fault |= (subpage == ((page + 1) % 16)); 73 want_fault |= (subpage == ((page + 1) % 16));
74 74
75 if (faulted != want_fault) { 75 if (faulted != want_fault) {
76 printf("Failed at 0x%p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n", 76 printf("Failed at %p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n",
77 addr, page, subpage, write, 77 addr, page, subpage, write,
78 want_fault ? "fault" : "pass", 78 want_fault ? "fault" : "pass",
79 faulted ? "fault" : "pass"); 79 faulted ? "fault" : "pass");
@@ -82,7 +82,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
82 82
83 if (faulted) { 83 if (faulted) {
84 if (dar != addr) { 84 if (dar != addr) {
85 printf("Fault expected at 0x%p and happened at 0x%p !\n", 85 printf("Fault expected at %p and happened at %p !\n",
86 addr, dar); 86 addr, dar);
87 } 87 }
88 faulted = 0; 88 faulted = 0;
@@ -162,7 +162,7 @@ int test_anon(void)
162 162
163 mallocblock = (void *)align; 163 mallocblock = (void *)align;
164 164
165 printf("allocated malloc block of 0x%lx bytes at 0x%p\n", 165 printf("allocated malloc block of 0x%lx bytes at %p\n",
166 mallocsize, mallocblock); 166 mallocsize, mallocblock);
167 167
168 printf("testing malloc block...\n"); 168 printf("testing malloc block...\n");
@@ -197,7 +197,7 @@ int test_file(void)
197 perror("failed to map file"); 197 perror("failed to map file");
198 return 1; 198 return 1;
199 } 199 }
200 printf("allocated %s for 0x%lx bytes at 0x%p\n", 200 printf("allocated %s for 0x%lx bytes at %p\n",
201 file_name, filesize, fileblock); 201 file_name, filesize, fileblock);
202 202
203 printf("testing file map...\n"); 203 printf("testing file map...\n");
@@ -207,14 +207,16 @@ int test_file(void)
207 207
208int main(int argc, char *argv[]) 208int main(int argc, char *argv[])
209{ 209{
210 test_harness(test_anon, "subpage_prot_anon"); 210 int rc;
211
212 rc = test_harness(test_anon, "subpage_prot_anon");
213 if (rc)
214 return rc;
211 215
212 if (argc > 1) 216 if (argc > 1)
213 file_name = argv[1]; 217 file_name = argv[1];
214 else 218 else
215 file_name = "tempfile"; 219 file_name = "tempfile";
216 220
217 test_harness(test_file, "subpage_prot_file"); 221 return test_harness(test_file, "subpage_prot_file");
218
219 return 0;
220} 222}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index e67452f1bcff..46681fec549b 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -15,7 +15,6 @@
15#include <sys/ioctl.h> 15#include <sys/ioctl.h>
16 16
17#include "trace.h" 17#include "trace.h"
18#include "reg.h"
19#include "ebb.h" 18#include "ebb.h"
20 19
21 20
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
index 5b1188f10c15..f923228bca22 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
@@ -7,7 +7,6 @@
7#include <stdlib.h> 7#include <stdlib.h>
8 8
9#include "ebb.h" 9#include "ebb.h"
10#include "reg.h"
11 10
12 11
13/* 12/*
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg.h b/tools/testing/selftests/powerpc/reg.h
index 5921b0dfe2e9..65bfdeeebdee 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg.h
+++ b/tools/testing/selftests/powerpc/reg.h
@@ -9,12 +9,12 @@
9#define __stringify_1(x) #x 9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x) 10#define __stringify(x) __stringify_1(x)
11 11
12#define mfspr(rn) ({unsigned long rval; \ 12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," __stringify(rn) \ 13 asm volatile("mfspr %0," _str(rn) \
14 : "=r" (rval)); rval; }) 14 : "=r" (rval)); rval; })
15#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : \ 15#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \
16 : "r" ((unsigned long)(v)) \ 16 : "r" ((unsigned long)(v)) \
17 : "memory") 17 : "memory")
18 18
19#define mb() asm volatile("sync" : : : "memory"); 19#define mb() asm volatile("sync" : : : "memory");
20 20
@@ -46,4 +46,10 @@
46#define SPRN_SDAR 781 46#define SPRN_SDAR 781
47#define SPRN_SIER 768 47#define SPRN_SIER 768
48 48
49#define SPRN_TEXASR 0x82
50#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
51#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
52#define TEXASR_FS 0x08000000
53#define SPRN_TAR 0x32f
54
49#endif /* _SELFTESTS_POWERPC_REG_H */ 55#endif /* _SELFTESTS_POWERPC_REG_H */
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 7d0f14b8cb2e..bb942db845bf 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -3,3 +3,6 @@ tm-syscall
3tm-signal-msr-resv 3tm-signal-msr-resv
4tm-signal-stack 4tm-signal-stack
5tm-vmxcopy 5tm-vmxcopy
6tm-fork
7tm-tar
8tm-tmspr
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 737f72c964e6..d0505dbd22d5 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy 1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy tm-fork tm-tar tm-tmspr
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -6,6 +6,7 @@ $(TEST_PROGS): ../harness.c ../utils.c
6 6
7tm-syscall: tm-syscall-asm.S 7tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include 8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
9tm-tmspr: CFLAGS += -pthread
9 10
10include ../../lib.mk 11include ../../lib.mk
11 12
diff --git a/tools/testing/selftests/powerpc/tm/tm-fork.c b/tools/testing/selftests/powerpc/tm/tm-fork.c
new file mode 100644
index 000000000000..8d48579b7778
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-fork.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Edited: Rashmica Gupta, Nov 2015
6 *
7 * This test does a fork syscall inside a transaction. Basic sniff test
8 * to see if we can enter the kernel during a transaction.
9 */
10
11#include <errno.h>
12#include <inttypes.h>
13#include <pthread.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17
18#include "utils.h"
19#include "tm.h"
20
21int test_fork(void)
22{
23 SKIP_IF(!have_htm());
24
25 asm __volatile__(
26 "tbegin.;"
27 "blt 1f; "
28 "li 0, 2;" /* fork syscall */
29 "sc ;"
30 "tend.;"
31 "1: ;"
32 : : : "memory", "r0");
33 /* If we reach here, we've passed. Otherwise we've probably crashed
34 * the kernel */
35
36 return 0;
37}
38
39int main(int argc, char *argv[])
40{
41 return test_harness(test_fork, "tm_fork");
42}
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index 8fde93d6021f..d9c49f41515e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -31,12 +31,6 @@
31#include "utils.h" 31#include "utils.h"
32#include "tm.h" 32#include "tm.h"
33 33
34#define TBEGIN ".long 0x7C00051D ;"
35#define TEND ".long 0x7C00055D ;"
36#define TCHECK ".long 0x7C00059C ;"
37#define TSUSPEND ".long 0x7C0005DD ;"
38#define TRESUME ".long 0x7C2005DD ;"
39#define SPRN_TEXASR 0x82
40#define SPRN_DSCR 0x03 34#define SPRN_DSCR 0x03
41 35
42int test_body(void) 36int test_body(void)
@@ -55,13 +49,13 @@ int test_body(void)
55 "mtspr %[sprn_dscr], 3;" 49 "mtspr %[sprn_dscr], 3;"
56 50
57 /* start and suspend a transaction */ 51 /* start and suspend a transaction */
58 TBEGIN 52 "tbegin.;"
59 "beq 1f;" 53 "beq 1f;"
60 TSUSPEND 54 "tsuspend.;"
61 55
62 /* hard loop until the transaction becomes doomed */ 56 /* hard loop until the transaction becomes doomed */
63 "2: ;" 57 "2: ;"
64 TCHECK 58 "tcheck 0;"
65 "bc 4, 0, 2b;" 59 "bc 4, 0, 2b;"
66 60
67 /* record DSCR and TEXASR */ 61 /* record DSCR and TEXASR */
@@ -70,8 +64,8 @@ int test_body(void)
70 "mfspr 3, %[sprn_texasr];" 64 "mfspr 3, %[sprn_texasr];"
71 "std 3, %[texasr];" 65 "std 3, %[texasr];"
72 66
73 TRESUME 67 "tresume.;"
74 TEND 68 "tend.;"
75 "li %[rv], 0;" 69 "li %[rv], 0;"
76 "1: ;" 70 "1: ;"
77 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) 71 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
index e44a238c1d77..1f0eb567438d 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -60,9 +60,9 @@ int tm_signal_stack()
60 exit(1); 60 exit(1);
61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */ 61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */
62 "1:" 62 "1:"
63 ".long 0x7C00051D ;" /* tbegin */ 63 "tbegin.;"
64 "beq 1b ;" /* retry forever */ 64 "beq 1b ;" /* retry forever */
65 ".long 0x7C0005DD ; ;" /* tsuspend */ 65 "tsuspend.;"
66 "ld 2, 0(1) ;" /* trigger segv" */ 66 "ld 2, 0(1) ;" /* trigger segv" */
67 : : : "memory"); 67 : : : "memory");
68 68
diff --git a/tools/testing/selftests/powerpc/tm/tm-tar.c b/tools/testing/selftests/powerpc/tm/tm-tar.c
new file mode 100644
index 000000000000..2d2fcc2b7a60
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tar.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 * Original: Michael Neuling 19/7/2013
5 * Edited: Rashmica Gupta 01/12/2015
6 *
7 * Do some transactions, see if the tar is corrupted.
8 * If the transaction is aborted, the TAR should be rolled back to the
9 * checkpointed value before the transaction began. The value written to
10 * TAR in suspended mode should only remain in TAR if the transaction
11 * completes.
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <string.h>
18
19#include "tm.h"
20#include "utils.h"
21
22int num_loops = 10000;
23
24int test_tar(void)
25{
26 int i;
27
28 SKIP_IF(!have_htm());
29
30 for (i = 0; i < num_loops; i++)
31 {
32 uint64_t result = 0;
33 asm __volatile__(
34 "li 7, 1;"
35 "mtspr %[tar], 7;" /* tar = 1 */
36 "tbegin.;"
37 "beq 3f;"
38 "li 4, 0x7000;" /* Loop lots, to use time */
39 "2:;" /* Start loop */
40 "li 7, 2;"
41 "mtspr %[tar], 7;" /* tar = 2 */
42 "tsuspend.;"
43 "li 7, 3;"
44 "mtspr %[tar], 7;" /* tar = 3 */
45 "tresume.;"
46 "subi 4, 4, 1;"
47 "cmpdi 4, 0;"
48 "bne 2b;"
49 "tend.;"
50
51 /* Transaction sucess! TAR should be 3 */
52 "mfspr 7, %[tar];"
53 "ori %[res], 7, 4;" // res = 3|4 = 7
54 "b 4f;"
55
56 /* Abort handler. TAR should be rolled back to 1 */
57 "3:;"
58 "mfspr 7, %[tar];"
59 "ori %[res], 7, 8;" // res = 1|8 = 9
60 "4:;"
61
62 : [res]"=r"(result)
63 : [tar]"i"(SPRN_TAR)
64 : "memory", "r0", "r4", "r7");
65
66 /* If result is anything else other than 7 or 9, the tar
67 * value must have been corrupted. */
68 if ((result != 7) && (result != 9))
69 return 1;
70 }
71 return 0;
72}
73
74int main(int argc, char *argv[])
75{
76 /* A low number of iterations (eg 100) can cause a false pass */
77 if (argc > 1) {
78 if (strcmp(argv[1], "-h") == 0) {
79 printf("Syntax:\n\t%s [<num loops>]\n",
80 argv[0]);
81 return 1;
82 } else {
83 num_loops = atoi(argv[1]);
84 }
85 }
86
87 printf("Starting, %d loops\n", num_loops);
88
89 return test_harness(test_tar, "tm_tar");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
new file mode 100644
index 000000000000..2bda81c7bf23
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Original: Michael Neuling 3/4/2014
6 * Modified: Rashmica Gupta 8/12/2015
7 *
8 * Check if any of the Transaction Memory SPRs get corrupted.
9 * - TFIAR - stores address of location of transaction failure
10 * - TFHAR - stores address of software failure handler (if transaction
11 * fails)
12 * - TEXASR - lots of info about the transacion(s)
13 *
14 * (1) create more threads than cpus
15 * (2) in each thread:
16 * (a) set TFIAR and TFHAR a unique value
17 * (b) loop for awhile, continually checking to see if
18 * either register has been corrupted.
19 *
20 * (3) Loop:
21 * (a) begin transaction
22 * (b) abort transaction
23 * (c) check TEXASR to see if FS has been corrupted
24 *
25 */
26
27#define _GNU_SOURCE
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <pthread.h>
32#include <string.h>
33
34#include "utils.h"
35#include "tm.h"
36
37int num_loops = 10000;
38int passed = 1;
39
40void tfiar_tfhar(void *in)
41{
42 int i, cpu;
43 unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd;
44 cpu_set_t cpuset;
45
46 CPU_ZERO(&cpuset);
47 cpu = (unsigned long)in >> 1;
48 CPU_SET(cpu, &cpuset);
49 sched_setaffinity(0, sizeof(cpuset), &cpuset);
50
51 /* TFIAR: Last bit has to be high so userspace can read register */
52 tfiar = ((unsigned long)in) + 1;
53 tfiar += 2;
54 mtspr(SPRN_TFIAR, tfiar);
55
56 /* TFHAR: Last two bits are reserved */
57 tfhar = ((unsigned long)in);
58 tfhar &= ~0x3UL;
59 tfhar += 4;
60 mtspr(SPRN_TFHAR, tfhar);
61
62 for (i = 0; i < num_loops; i++) {
63 tfhar_rd = mfspr(SPRN_TFHAR);
64 tfiar_rd = mfspr(SPRN_TFIAR);
65 if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) {
66 passed = 0;
67 return;
68 }
69 }
70 return;
71}
72
73void texasr(void *in)
74{
75 unsigned long i;
76 uint64_t result = 0;
77
78 for (i = 0; i < num_loops; i++) {
79 asm __volatile__(
80 "tbegin.;"
81 "beq 3f ;"
82 "tabort. 0 ;"
83 "tend.;"
84
85 /* Abort handler */
86 "3: ;"
87 ::: "memory");
88
89 /* Check the TEXASR */
90 result = mfspr(SPRN_TEXASR);
91 if ((result & TEXASR_FS) == 0) {
92 passed = 0;
93 return;
94 }
95 }
96 return;
97}
98
99int test_tmspr()
100{
101 pthread_t thread;
102 int thread_num;
103 unsigned long i;
104
105 SKIP_IF(!have_htm());
106
107 /* To cause some context switching */
108 thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
109
110 /* Test TFIAR and TFHAR */
111 for (i = 0 ; i < thread_num ; i += 2){
112 if (pthread_create(&thread, NULL, (void*)tfiar_tfhar, (void *)i))
113 return EXIT_FAILURE;
114 }
115 if (pthread_join(thread, NULL) != 0)
116 return EXIT_FAILURE;
117
118 /* Test TEXASR */
119 for (i = 0 ; i < thread_num ; i++){
120 if (pthread_create(&thread, NULL, (void*)texasr, (void *)i))
121 return EXIT_FAILURE;
122 }
123 if (pthread_join(thread, NULL) != 0)
124 return EXIT_FAILURE;
125
126 if (passed)
127 return 0;
128 else
129 return 1;
130}
131
132int main(int argc, char *argv[])
133{
134 if (argc > 1) {
135 if (strcmp(argv[1], "-h") == 0) {
136 printf("Syntax:\t [<num loops>]\n");
137 return 0;
138 } else {
139 num_loops = atoi(argv[1]);
140 }
141 }
142 return test_harness(test_tmspr, "tm_tmspr");
143}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index 175ac6ad10dd..a985cfaa535e 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -6,9 +6,12 @@
6#ifndef _SELFTESTS_POWERPC_UTILS_H 6#ifndef _SELFTESTS_POWERPC_UTILS_H
7#define _SELFTESTS_POWERPC_UTILS_H 7#define _SELFTESTS_POWERPC_UTILS_H
8 8
9#define __cacheline_aligned __attribute__((aligned(128)))
10
9#include <stdint.h> 11#include <stdint.h>
10#include <stdbool.h> 12#include <stdbool.h>
11#include <linux/auxvec.h> 13#include <linux/auxvec.h>
14#include "reg.h"
12 15
13/* Avoid headaches with PRI?64 - just use %ll? always */ 16/* Avoid headaches with PRI?64 - just use %ll? always */
14typedef unsigned long long u64; 17typedef unsigned long long u64;
@@ -54,4 +57,9 @@ do { \
54#define _str(s) #s 57#define _str(s) #s
55#define str(s) _str(s) 58#define str(s) _str(s)
56 59
60/* POWER9 feature */
61#ifndef PPC_FEATURE2_ARCH_3_00
62#define PPC_FEATURE2_ARCH_3_00 0x00800000
63#endif
64
57#endif /* _SELFTESTS_POWERPC_UTILS_H */ 65#endif /* _SELFTESTS_POWERPC_UTILS_H */
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 150829dd7998..2e58549b2f02 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -5,6 +5,7 @@
5 * Test code for seccomp bpf. 5 * Test code for seccomp bpf.
6 */ 6 */
7 7
8#include <sys/types.h>
8#include <asm/siginfo.h> 9#include <asm/siginfo.h>
9#define __have_siginfo_t 1 10#define __have_siginfo_t 1
10#define __have_sigval_t 1 11#define __have_sigval_t 1
@@ -14,7 +15,6 @@
14#include <linux/filter.h> 15#include <linux/filter.h>
15#include <sys/prctl.h> 16#include <sys/prctl.h>
16#include <sys/ptrace.h> 17#include <sys/ptrace.h>
17#include <sys/types.h>
18#include <sys/user.h> 18#include <sys/user.h>
19#include <linux/prctl.h> 19#include <linux/prctl.h>
20#include <linux/ptrace.h> 20#include <linux/ptrace.h>
@@ -1234,6 +1234,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1234# define ARCH_REGS struct user_pt_regs 1234# define ARCH_REGS struct user_pt_regs
1235# define SYSCALL_NUM regs[8] 1235# define SYSCALL_NUM regs[8]
1236# define SYSCALL_RET regs[0] 1236# define SYSCALL_RET regs[0]
1237#elif defined(__hppa__)
1238# define ARCH_REGS struct user_regs_struct
1239# define SYSCALL_NUM gr[20]
1240# define SYSCALL_RET gr[28]
1237#elif defined(__powerpc__) 1241#elif defined(__powerpc__)
1238# define ARCH_REGS struct pt_regs 1242# define ARCH_REGS struct pt_regs
1239# define SYSCALL_NUM gpr[0] 1243# define SYSCALL_NUM gpr[0]
@@ -1242,6 +1246,12 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1242# define ARCH_REGS s390_regs 1246# define ARCH_REGS s390_regs
1243# define SYSCALL_NUM gprs[2] 1247# define SYSCALL_NUM gprs[2]
1244# define SYSCALL_RET gprs[2] 1248# define SYSCALL_RET gprs[2]
1249#elif defined(__mips__)
1250# define ARCH_REGS struct pt_regs
1251# define SYSCALL_NUM regs[2]
1252# define SYSCALL_SYSCALL_NUM regs[4]
1253# define SYSCALL_RET regs[2]
1254# define SYSCALL_NUM_RET_SHARE_REG
1245#else 1255#else
1246# error "Do not know how to find your architecture's registers and syscalls" 1256# error "Do not know how to find your architecture's registers and syscalls"
1247#endif 1257#endif
@@ -1249,7 +1259,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1249/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for 1259/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1250 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux). 1260 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1251 */ 1261 */
1252#if defined(__x86_64__) || defined(__i386__) 1262#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
1253#define HAVE_GETREGS 1263#define HAVE_GETREGS
1254#endif 1264#endif
1255 1265
@@ -1273,6 +1283,10 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1273 } 1283 }
1274#endif 1284#endif
1275 1285
1286#if defined(__mips__)
1287 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1288 return regs.SYSCALL_SYSCALL_NUM;
1289#endif
1276 return regs.SYSCALL_NUM; 1290 return regs.SYSCALL_NUM;
1277} 1291}
1278 1292
@@ -1293,10 +1307,17 @@ void change_syscall(struct __test_metadata *_metadata,
1293 EXPECT_EQ(0, ret); 1307 EXPECT_EQ(0, ret);
1294 1308
1295#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ 1309#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
1296 defined(__s390__) 1310 defined(__s390__) || defined(__hppa__)
1297 { 1311 {
1298 regs.SYSCALL_NUM = syscall; 1312 regs.SYSCALL_NUM = syscall;
1299 } 1313 }
1314#elif defined(__mips__)
1315 {
1316 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1317 regs.SYSCALL_SYSCALL_NUM = syscall;
1318 else
1319 regs.SYSCALL_NUM = syscall;
1320 }
1300 1321
1301#elif defined(__arm__) 1322#elif defined(__arm__)
1302# ifndef PTRACE_SET_SYSCALL 1323# ifndef PTRACE_SET_SYSCALL
@@ -1327,7 +1348,11 @@ void change_syscall(struct __test_metadata *_metadata,
1327 1348
1328 /* If syscall is skipped, change return value. */ 1349 /* If syscall is skipped, change return value. */
1329 if (syscall == -1) 1350 if (syscall == -1)
1351#ifdef SYSCALL_NUM_RET_SHARE_REG
1352 TH_LOG("Can't modify syscall return on this architecture");
1353#else
1330 regs.SYSCALL_RET = 1; 1354 regs.SYSCALL_RET = 1;
1355#endif
1331 1356
1332#ifdef HAVE_GETREGS 1357#ifdef HAVE_GETREGS
1333 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs); 1358 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
@@ -1465,8 +1490,13 @@ TEST_F(TRACE_syscall, syscall_dropped)
1465 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); 1490 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1466 ASSERT_EQ(0, ret); 1491 ASSERT_EQ(0, ret);
1467 1492
1493#ifdef SYSCALL_NUM_RET_SHARE_REG
1494 /* gettid has been skipped */
1495 EXPECT_EQ(-1, syscall(__NR_gettid));
1496#else
1468 /* gettid has been skipped and an altered return value stored. */ 1497 /* gettid has been skipped and an altered return value stored. */
1469 EXPECT_EQ(1, syscall(__NR_gettid)); 1498 EXPECT_EQ(1, syscall(__NR_gettid));
1499#endif
1470 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1500 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1471} 1501}
1472 1502
@@ -1479,6 +1509,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
1479# define __NR_seccomp 383 1509# define __NR_seccomp 383
1480# elif defined(__aarch64__) 1510# elif defined(__aarch64__)
1481# define __NR_seccomp 277 1511# define __NR_seccomp 277
1512# elif defined(__hppa__)
1513# define __NR_seccomp 338
1482# elif defined(__powerpc__) 1514# elif defined(__powerpc__)
1483# define __NR_seccomp 358 1515# define __NR_seccomp 358
1484# elif defined(__s390__) 1516# elif defined(__s390__)
diff --git a/tools/testing/selftests/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c
index c87957295f74..0bc737a75150 100644
--- a/tools/testing/selftests/vm/thuge-gen.c
+++ b/tools/testing/selftests/vm/thuge-gen.c
@@ -30,7 +30,9 @@
30#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) 30#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
31#define MAP_HUGE_SHIFT 26 31#define MAP_HUGE_SHIFT 26
32#define MAP_HUGE_MASK 0x3f 32#define MAP_HUGE_MASK 0x3f
33#if !defined(MAP_HUGETLB)
33#define MAP_HUGETLB 0x40000 34#define MAP_HUGETLB 0x40000
35#endif
34 36
35#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ 37#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
36#define SHM_HUGE_SHIFT 26 38#define SHM_HUGE_SHIFT 26
diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
index 7c8f8a4d54e4..90daf95c0804 100644
--- a/tools/usb/usbip/libsrc/Makefile.am
+++ b/tools/usb/usbip/libsrc/Makefile.am
@@ -4,5 +4,7 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@
4 4
5lib_LTLIBRARIES := libusbip.la 5lib_LTLIBRARIES := libusbip.la
6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ 6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
7 usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \ 7 usbip_device_driver.c usbip_device_driver.h \
8 usbip_common.c usbip_common.h usbip_host_common.h \
9 usbip_host_common.c vhci_driver.c vhci_driver.h \
8 sysfs_utils.c sysfs_utils.h 10 sysfs_utils.c sysfs_utils.h
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index 15fe792e1e96..51ef5fe485dd 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -25,9 +25,12 @@
25#define VHCI_STATE_PATH "/var/run/vhci_hcd" 25#define VHCI_STATE_PATH "/var/run/vhci_hcd"
26#endif 26#endif
27 27
28#define VUDC_DEVICE_DESCR_FILE "dev_desc"
29
28/* kernel module names */ 30/* kernel module names */
29#define USBIP_CORE_MOD_NAME "usbip-core" 31#define USBIP_CORE_MOD_NAME "usbip-core"
30#define USBIP_HOST_DRV_NAME "usbip-host" 32#define USBIP_HOST_DRV_NAME "usbip-host"
33#define USBIP_DEVICE_DRV_NAME "usbip-vudc"
31#define USBIP_VHCI_DRV_NAME "vhci_hcd" 34#define USBIP_VHCI_DRV_NAME "vhci_hcd"
32 35
33/* sysfs constants */ 36/* sysfs constants */
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c
new file mode 100644
index 000000000000..e059b7d1ec5b
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <fcntl.h>
25#include <string.h>
26#include <linux/usb/ch9.h>
27
28#include <unistd.h>
29
30#include "usbip_host_common.h"
31#include "usbip_device_driver.h"
32
33#undef PROGNAME
34#define PROGNAME "libusbip"
35
36#define copy_descr_attr16(dev, descr, attr) \
37 ((dev)->attr = le16toh((descr)->attr)) \
38
39#define copy_descr_attr(dev, descr, attr) \
40 ((dev)->attr = (descr)->attr) \
41
42#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
43
44static struct {
45 enum usb_device_speed speed;
46 const char *name;
47} speed_names[] = {
48 {
49 .speed = USB_SPEED_UNKNOWN,
50 .name = "UNKNOWN",
51 },
52 {
53 .speed = USB_SPEED_LOW,
54 .name = "low-speed",
55 },
56 {
57 .speed = USB_SPEED_FULL,
58 .name = "full-speed",
59 },
60 {
61 .speed = USB_SPEED_HIGH,
62 .name = "high-speed",
63 },
64 {
65 .speed = USB_SPEED_WIRELESS,
66 .name = "wireless",
67 },
68 {
69 .speed = USB_SPEED_SUPER,
70 .name = "super-speed",
71 },
72};
73
74static
75int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
76{
77 const char *path, *name;
78 char filepath[SYSFS_PATH_MAX];
79 struct usb_device_descriptor descr;
80 unsigned i;
81 FILE *fd = NULL;
82 struct udev_device *plat;
83 const char *speed;
84 int ret = 0;
85
86 plat = udev_device_get_parent(sdev);
87 path = udev_device_get_syspath(plat);
88 snprintf(filepath, SYSFS_PATH_MAX, "%s/%s",
89 path, VUDC_DEVICE_DESCR_FILE);
90 fd = fopen(filepath, "r");
91 if (!fd)
92 return -1;
93 ret = fread((char *) &descr, sizeof(descr), 1, fd);
94 if (ret < 0)
95 return -1;
96 fclose(fd);
97
98 copy_descr_attr(dev, &descr, bDeviceClass);
99 copy_descr_attr(dev, &descr, bDeviceSubClass);
100 copy_descr_attr(dev, &descr, bDeviceProtocol);
101 copy_descr_attr(dev, &descr, bNumConfigurations);
102 copy_descr_attr16(dev, &descr, idVendor);
103 copy_descr_attr16(dev, &descr, idProduct);
104 copy_descr_attr16(dev, &descr, bcdDevice);
105
106 strncpy(dev->path, path, SYSFS_PATH_MAX);
107
108 dev->speed = USB_SPEED_UNKNOWN;
109 speed = udev_device_get_sysattr_value(sdev, "current_speed");
110 if (speed) {
111 for (i = 0; i < ARRAY_SIZE(speed_names); i++) {
112 if (!strcmp(speed_names[i].name, speed)) {
113 dev->speed = speed_names[i].speed;
114 break;
115 }
116 }
117 }
118
119 /* Only used for user output, little sense to output them in general */
120 dev->bNumInterfaces = 0;
121 dev->bConfigurationValue = 0;
122 dev->busnum = 0;
123
124 name = udev_device_get_sysname(plat);
125 strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
126 return 0;
127}
128
129static int is_my_device(struct udev_device *dev)
130{
131 const char *driver;
132
133 driver = udev_device_get_property_value(dev, "USB_UDC_NAME");
134 return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME);
135}
136
137static int usbip_device_driver_open(struct usbip_host_driver *hdriver)
138{
139 int ret;
140
141 hdriver->ndevs = 0;
142 INIT_LIST_HEAD(&hdriver->edev_list);
143
144 ret = usbip_generic_driver_open(hdriver);
145 if (ret)
146 err("please load " USBIP_CORE_MOD_NAME ".ko and "
147 USBIP_DEVICE_DRV_NAME ".ko!");
148
149 return ret;
150}
151
152struct usbip_host_driver device_driver = {
153 .edev_list = LIST_HEAD_INIT(device_driver.edev_list),
154 .udev_subsystem = "udc",
155 .ops = {
156 .open = usbip_device_driver_open,
157 .close = usbip_generic_driver_close,
158 .refresh_device_list = usbip_generic_refresh_device_list,
159 .get_device = usbip_generic_get_device,
160 .read_device = read_usb_vudc_device,
161 .is_my_device = is_my_device,
162 },
163};
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.h b/tools/usb/usbip/libsrc/usbip_device_driver.h
new file mode 100644
index 000000000000..54cb658b37a3
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_DEVICE_DRIVER_H
25#define __USBIP_DEVICE_DRIVER_H
26
27#include <stdint.h>
28#include "usbip_common.h"
29#include "usbip_host_common.h"
30#include "list.h"
31
32extern struct usbip_host_driver device_driver;
33
34#endif /* __USBIP_DEVICE_DRIVER_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
new file mode 100644
index 000000000000..9d415228883d
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27
28#include <errno.h>
29#include <unistd.h>
30
31#include <libudev.h>
32
33#include "usbip_common.h"
34#include "usbip_host_common.h"
35#include "list.h"
36#include "sysfs_utils.h"
37
38struct udev *udev_context;
39
40static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
41{
42 char status_attr_path[SYSFS_PATH_MAX];
43 int fd;
44 int length;
45 char status;
46 int value = 0;
47
48 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
49 udev->path);
50
51 fd = open(status_attr_path, O_RDONLY);
52 if (fd < 0) {
53 err("error opening attribute %s", status_attr_path);
54 return -1;
55 }
56
57 length = read(fd, &status, 1);
58 if (length < 0) {
59 err("error reading attribute %s", status_attr_path);
60 close(fd);
61 return -1;
62 }
63
64 value = atoi(&status);
65
66 return value;
67}
68
69static
70struct usbip_exported_device *usbip_exported_device_new(
71 struct usbip_host_driver *hdriver, const char *sdevpath)
72{
73 struct usbip_exported_device *edev = NULL;
74 struct usbip_exported_device *edev_old;
75 size_t size;
76 int i;
77
78 edev = calloc(1, sizeof(struct usbip_exported_device));
79
80 edev->sudev =
81 udev_device_new_from_syspath(udev_context, sdevpath);
82 if (!edev->sudev) {
83 err("udev_device_new_from_syspath: %s", sdevpath);
84 goto err;
85 }
86
87 if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0)
88 goto err;
89
90 edev->status = read_attr_usbip_status(&edev->udev);
91 if (edev->status < 0)
92 goto err;
93
94 /* reallocate buffer to include usb interface data */
95 size = sizeof(struct usbip_exported_device) +
96 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
97
98 edev_old = edev;
99 edev = realloc(edev, size);
100 if (!edev) {
101 edev = edev_old;
102 dbg("realloc failed");
103 goto err;
104 }
105
106 for (i = 0; i < edev->udev.bNumInterfaces; i++) {
107 /* vudc does not support reading interfaces */
108 if (!hdriver->ops.read_interface)
109 break;
110 hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]);
111 }
112
113 return edev;
114err:
115 if (edev->sudev)
116 udev_device_unref(edev->sudev);
117 if (edev)
118 free(edev);
119
120 return NULL;
121}
122
123static int refresh_exported_devices(struct usbip_host_driver *hdriver)
124{
125 struct usbip_exported_device *edev;
126 struct udev_enumerate *enumerate;
127 struct udev_list_entry *devices, *dev_list_entry;
128 struct udev_device *dev;
129 const char *path;
130
131 enumerate = udev_enumerate_new(udev_context);
132 udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem);
133 udev_enumerate_scan_devices(enumerate);
134
135 devices = udev_enumerate_get_list_entry(enumerate);
136
137 udev_list_entry_foreach(dev_list_entry, devices) {
138 path = udev_list_entry_get_name(dev_list_entry);
139 dev = udev_device_new_from_syspath(udev_context,
140 path);
141 if (dev == NULL)
142 continue;
143
144 /* Check whether device uses usbip driver. */
145 if (hdriver->ops.is_my_device(dev)) {
146 edev = usbip_exported_device_new(hdriver, path);
147 if (!edev) {
148 dbg("usbip_exported_device_new failed");
149 continue;
150 }
151
152 list_add(&edev->node, &hdriver->edev_list);
153 hdriver->ndevs++;
154 }
155 }
156
157 return 0;
158}
159
160static void usbip_exported_device_destroy(struct list_head *devs)
161{
162 struct list_head *i, *tmp;
163 struct usbip_exported_device *edev;
164
165 list_for_each_safe(i, tmp, devs) {
166 edev = list_entry(i, struct usbip_exported_device, node);
167 list_del(i);
168 free(edev);
169 }
170}
171
172int usbip_generic_driver_open(struct usbip_host_driver *hdriver)
173{
174 int rc;
175
176 udev_context = udev_new();
177 if (!udev_context) {
178 err("udev_new failed");
179 return -1;
180 }
181
182 rc = refresh_exported_devices(hdriver);
183 if (rc < 0)
184 goto err;
185 return 0;
186err:
187 udev_unref(udev_context);
188 return -1;
189}
190
191void usbip_generic_driver_close(struct usbip_host_driver *hdriver)
192{
193 if (!hdriver)
194 return;
195
196 usbip_exported_device_destroy(&hdriver->edev_list);
197
198 udev_unref(udev_context);
199}
200
201int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver)
202{
203 int rc;
204
205 usbip_exported_device_destroy(&hdriver->edev_list);
206
207 hdriver->ndevs = 0;
208 INIT_LIST_HEAD(&hdriver->edev_list);
209
210 rc = refresh_exported_devices(hdriver);
211 if (rc < 0)
212 return -1;
213
214 return 0;
215}
216
217int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
218{
219 char attr_name[] = "usbip_sockfd";
220 char sockfd_attr_path[SYSFS_PATH_MAX];
221 char sockfd_buff[30];
222 int ret;
223
224 if (edev->status != SDEV_ST_AVAILABLE) {
225 dbg("device not available: %s", edev->udev.busid);
226 switch (edev->status) {
227 case SDEV_ST_ERROR:
228 dbg("status SDEV_ST_ERROR");
229 break;
230 case SDEV_ST_USED:
231 dbg("status SDEV_ST_USED");
232 break;
233 default:
234 dbg("status unknown: 0x%x", edev->status);
235 }
236 return -1;
237 }
238
239 /* only the first interface is true */
240 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
241 edev->udev.path, attr_name);
242
243 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
244
245 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
246 strlen(sockfd_buff));
247 if (ret < 0) {
248 err("write_sysfs_attribute failed: sockfd %s to %s",
249 sockfd_buff, sockfd_attr_path);
250 return ret;
251 }
252
253 info("connect: %s", edev->udev.busid);
254
255 return ret;
256}
257
258struct usbip_exported_device *usbip_generic_get_device(
259 struct usbip_host_driver *hdriver, int num)
260{
261 struct list_head *i;
262 struct usbip_exported_device *edev;
263 int cnt = 0;
264
265 list_for_each(i, &hdriver->edev_list) {
266 edev = list_entry(i, struct usbip_exported_device, node);
267 if (num == cnt)
268 return edev;
269 cnt++;
270 }
271
272 return NULL;
273}
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.h b/tools/usb/usbip/libsrc/usbip_host_common.h
new file mode 100644
index 000000000000..a64b8033fe64
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.h
@@ -0,0 +1,104 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_HOST_COMMON_H
25#define __USBIP_HOST_COMMON_H
26
27#include <stdint.h>
28#include <libudev.h>
29#include <errno.h>
30#include "list.h"
31#include "usbip_common.h"
32#include "sysfs_utils.h"
33
34struct usbip_host_driver;
35
36struct usbip_host_driver_ops {
37 int (*open)(struct usbip_host_driver *hdriver);
38 void (*close)(struct usbip_host_driver *hdriver);
39 int (*refresh_device_list)(struct usbip_host_driver *hdriver);
40 struct usbip_exported_device * (*get_device)(
41 struct usbip_host_driver *hdriver, int num);
42
43 int (*read_device)(struct udev_device *sdev,
44 struct usbip_usb_device *dev);
45 int (*read_interface)(struct usbip_usb_device *udev, int i,
46 struct usbip_usb_interface *uinf);
47 int (*is_my_device)(struct udev_device *udev);
48};
49
50struct usbip_host_driver {
51 int ndevs;
52 /* list of exported device */
53 struct list_head edev_list;
54 const char *udev_subsystem;
55 struct usbip_host_driver_ops ops;
56};
57
58struct usbip_exported_device {
59 struct udev_device *sudev;
60 int32_t status;
61 struct usbip_usb_device udev;
62 struct list_head node;
63 struct usbip_usb_interface uinf[];
64};
65
66/* External API to access the driver */
67static inline int usbip_driver_open(struct usbip_host_driver *hdriver)
68{
69 if (!hdriver->ops.open)
70 return -EOPNOTSUPP;
71 return hdriver->ops.open(hdriver);
72}
73
74static inline void usbip_driver_close(struct usbip_host_driver *hdriver)
75{
76 if (!hdriver->ops.close)
77 return;
78 hdriver->ops.close(hdriver);
79}
80
81static inline int usbip_refresh_device_list(struct usbip_host_driver *hdriver)
82{
83 if (!hdriver->ops.refresh_device_list)
84 return -EOPNOTSUPP;
85 return hdriver->ops.refresh_device_list(hdriver);
86}
87
88static inline struct usbip_exported_device *
89usbip_get_device(struct usbip_host_driver *hdriver, int num)
90{
91 if (!hdriver->ops.get_device)
92 return NULL;
93 return hdriver->ops.get_device(hdriver, num);
94}
95
96/* Helper functions for implementing driver backend */
97int usbip_generic_driver_open(struct usbip_host_driver *hdriver);
98void usbip_generic_driver_close(struct usbip_host_driver *hdriver);
99int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver);
100int usbip_export_device(struct usbip_exported_device *edev, int sockfd);
101struct usbip_exported_device *usbip_generic_get_device(
102 struct usbip_host_driver *hdriver, int num);
103
104#endif /* __USBIP_HOST_COMMON_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c
index bef08d5c44e8..4de6edc54d35 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.c
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -16,265 +19,47 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 20 */
18 21
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
23#include <errno.h>
24#include <unistd.h> 22#include <unistd.h>
25
26#include <libudev.h> 23#include <libudev.h>
27 24
28#include "usbip_common.h" 25#include "usbip_host_common.h"
29#include "usbip_host_driver.h" 26#include "usbip_host_driver.h"
30#include "list.h"
31#include "sysfs_utils.h"
32 27
33#undef PROGNAME 28#undef PROGNAME
34#define PROGNAME "libusbip" 29#define PROGNAME "libusbip"
35 30
36struct usbip_host_driver *host_driver; 31static int is_my_device(struct udev_device *dev)
37struct udev *udev_context;
38
39static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
40{
41 char status_attr_path[SYSFS_PATH_MAX];
42 int fd;
43 int length;
44 char status;
45 int value = 0;
46
47 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
48 udev->path);
49
50 fd = open(status_attr_path, O_RDONLY);
51 if (fd < 0) {
52 err("error opening attribute %s", status_attr_path);
53 return -1;
54 }
55
56 length = read(fd, &status, 1);
57 if (length < 0) {
58 err("error reading attribute %s", status_attr_path);
59 close(fd);
60 return -1;
61 }
62
63 value = atoi(&status);
64
65 return value;
66}
67
68static
69struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
70{
71 struct usbip_exported_device *edev = NULL;
72 struct usbip_exported_device *edev_old;
73 size_t size;
74 int i;
75
76 edev = calloc(1, sizeof(struct usbip_exported_device));
77
78 edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
79 if (!edev->sudev) {
80 err("udev_device_new_from_syspath: %s", sdevpath);
81 goto err;
82 }
83
84 read_usb_device(edev->sudev, &edev->udev);
85
86 edev->status = read_attr_usbip_status(&edev->udev);
87 if (edev->status < 0)
88 goto err;
89
90 /* reallocate buffer to include usb interface data */
91 size = sizeof(struct usbip_exported_device) +
92 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
93
94 edev_old = edev;
95 edev = realloc(edev, size);
96 if (!edev) {
97 edev = edev_old;
98 dbg("realloc failed");
99 goto err;
100 }
101
102 for (i = 0; i < edev->udev.bNumInterfaces; i++)
103 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
104
105 return edev;
106err:
107 if (edev->sudev)
108 udev_device_unref(edev->sudev);
109 if (edev)
110 free(edev);
111
112 return NULL;
113}
114
115static int refresh_exported_devices(void)
116{ 32{
117 struct usbip_exported_device *edev;
118 struct udev_enumerate *enumerate;
119 struct udev_list_entry *devices, *dev_list_entry;
120 struct udev_device *dev;
121 const char *path;
122 const char *driver; 33 const char *driver;
123 34
124 enumerate = udev_enumerate_new(udev_context); 35 driver = udev_device_get_driver(dev);
125 udev_enumerate_add_match_subsystem(enumerate, "usb"); 36 return driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME);
126 udev_enumerate_scan_devices(enumerate);
127
128 devices = udev_enumerate_get_list_entry(enumerate);
129
130 udev_list_entry_foreach(dev_list_entry, devices) {
131 path = udev_list_entry_get_name(dev_list_entry);
132 dev = udev_device_new_from_syspath(udev_context, path);
133 if (dev == NULL)
134 continue;
135
136 /* Check whether device uses usbip-host driver. */
137 driver = udev_device_get_driver(dev);
138 if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
139 edev = usbip_exported_device_new(path);
140 if (!edev) {
141 dbg("usbip_exported_device_new failed");
142 continue;
143 }
144
145 list_add(&edev->node, &host_driver->edev_list);
146 host_driver->ndevs++;
147 }
148 }
149
150 return 0;
151}
152
153static void usbip_exported_device_destroy(void)
154{
155 struct list_head *i, *tmp;
156 struct usbip_exported_device *edev;
157
158 list_for_each_safe(i, tmp, &host_driver->edev_list) {
159 edev = list_entry(i, struct usbip_exported_device, node);
160 list_del(i);
161 free(edev);
162 }
163} 37}
164 38
165int usbip_host_driver_open(void) 39static int usbip_host_driver_open(struct usbip_host_driver *hdriver)
166{ 40{
167 int rc;
168
169 udev_context = udev_new();
170 if (!udev_context) {
171 err("udev_new failed");
172 return -1;
173 }
174
175 host_driver = calloc(1, sizeof(*host_driver));
176
177 host_driver->ndevs = 0;
178 INIT_LIST_HEAD(&host_driver->edev_list);
179
180 rc = refresh_exported_devices();
181 if (rc < 0)
182 goto err_free_host_driver;
183
184 return 0;
185
186err_free_host_driver:
187 free(host_driver);
188 host_driver = NULL;
189
190 udev_unref(udev_context);
191
192 return -1;
193}
194
195void usbip_host_driver_close(void)
196{
197 if (!host_driver)
198 return;
199
200 usbip_exported_device_destroy();
201
202 free(host_driver);
203 host_driver = NULL;
204
205 udev_unref(udev_context);
206}
207
208int usbip_host_refresh_device_list(void)
209{
210 int rc;
211
212 usbip_exported_device_destroy();
213
214 host_driver->ndevs = 0;
215 INIT_LIST_HEAD(&host_driver->edev_list);
216
217 rc = refresh_exported_devices();
218 if (rc < 0)
219 return -1;
220
221 return 0;
222}
223
224int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
225{
226 char attr_name[] = "usbip_sockfd";
227 char sockfd_attr_path[SYSFS_PATH_MAX];
228 char sockfd_buff[30];
229 int ret; 41 int ret;
230 42
231 if (edev->status != SDEV_ST_AVAILABLE) { 43 hdriver->ndevs = 0;
232 dbg("device not available: %s", edev->udev.busid); 44 INIT_LIST_HEAD(&hdriver->edev_list);
233 switch (edev->status) {
234 case SDEV_ST_ERROR:
235 dbg("status SDEV_ST_ERROR");
236 break;
237 case SDEV_ST_USED:
238 dbg("status SDEV_ST_USED");
239 break;
240 default:
241 dbg("status unknown: 0x%x", edev->status);
242 }
243 return -1;
244 }
245
246 /* only the first interface is true */
247 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
248 edev->udev.path, attr_name);
249
250 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
251
252 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
253 strlen(sockfd_buff));
254 if (ret < 0) {
255 err("write_sysfs_attribute failed: sockfd %s to %s",
256 sockfd_buff, sockfd_attr_path);
257 return ret;
258 }
259
260 info("connect: %s", edev->udev.busid);
261 45
46 ret = usbip_generic_driver_open(hdriver);
47 if (ret)
48 err("please load " USBIP_CORE_MOD_NAME ".ko and "
49 USBIP_HOST_DRV_NAME ".ko!");
262 return ret; 50 return ret;
263} 51}
264 52
265struct usbip_exported_device *usbip_host_get_device(int num) 53struct usbip_host_driver host_driver = {
266{ 54 .edev_list = LIST_HEAD_INIT(host_driver.edev_list),
267 struct list_head *i; 55 .udev_subsystem = "usb",
268 struct usbip_exported_device *edev; 56 .ops = {
269 int cnt = 0; 57 .open = usbip_host_driver_open,
270 58 .close = usbip_generic_driver_close,
271 list_for_each(i, &host_driver->edev_list) { 59 .refresh_device_list = usbip_generic_refresh_device_list,
272 edev = list_entry(i, struct usbip_exported_device, node); 60 .get_device = usbip_generic_get_device,
273 if (num == cnt) 61 .read_device = read_usb_device,
274 return edev; 62 .read_interface = read_usb_interface,
275 else 63 .is_my_device = is_my_device,
276 cnt++; 64 },
277 } 65};
278
279 return NULL;
280}
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h
index 2a31f855c616..77f07e72a7fe 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.h
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.h
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -22,28 +25,8 @@
22#include <stdint.h> 25#include <stdint.h>
23#include "usbip_common.h" 26#include "usbip_common.h"
24#include "list.h" 27#include "list.h"
28#include "usbip_host_common.h"
25 29
26struct usbip_host_driver { 30extern struct usbip_host_driver host_driver;
27 int ndevs;
28 /* list of exported device */
29 struct list_head edev_list;
30};
31
32struct usbip_exported_device {
33 struct udev_device *sudev;
34 int32_t status;
35 struct usbip_usb_device udev;
36 struct list_head node;
37 struct usbip_usb_interface uinf[];
38};
39
40extern struct usbip_host_driver *host_driver;
41
42int usbip_host_driver_open(void);
43void usbip_host_driver_close(void);
44
45int usbip_host_refresh_device_list(void);
46int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
47struct usbip_exported_device *usbip_host_get_device(int num);
48 31
49#endif /* __USBIP_HOST_DRIVER_H */ 32#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index d58a14dfc094..70a6b507fb62 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -36,7 +39,8 @@
36static const char usbip_attach_usage_string[] = 39static const char usbip_attach_usage_string[] =
37 "usbip attach <args>\n" 40 "usbip attach <args>\n"
38 " -r, --remote=<host> The machine with exported USB devices\n" 41 " -r, --remote=<host> The machine with exported USB devices\n"
39 " -b, --busid=<busid> Busid of the device on <host>\n"; 42 " -b, --busid=<busid> Busid of the device on <host>\n"
43 " -d, --device=<devid> Id of the virtual UDC on <host>\n";
40 44
41void usbip_attach_usage(void) 45void usbip_attach_usage(void)
42{ 46{
@@ -203,6 +207,7 @@ int usbip_attach(int argc, char *argv[])
203 static const struct option opts[] = { 207 static const struct option opts[] = {
204 { "remote", required_argument, NULL, 'r' }, 208 { "remote", required_argument, NULL, 'r' },
205 { "busid", required_argument, NULL, 'b' }, 209 { "busid", required_argument, NULL, 'b' },
210 { "device", required_argument, NULL, 'd' },
206 { NULL, 0, NULL, 0 } 211 { NULL, 0, NULL, 0 }
207 }; 212 };
208 char *host = NULL; 213 char *host = NULL;
@@ -211,7 +216,7 @@ int usbip_attach(int argc, char *argv[])
211 int ret = -1; 216 int ret = -1;
212 217
213 for (;;) { 218 for (;;) {
214 opt = getopt_long(argc, argv, "r:b:", opts, NULL); 219 opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
215 220
216 if (opt == -1) 221 if (opt == -1)
217 break; 222 break;
@@ -220,6 +225,7 @@ int usbip_attach(int argc, char *argv[])
220 case 'r': 225 case 'r':
221 host = optarg; 226 host = optarg;
222 break; 227 break;
228 case 'd':
223 case 'b': 229 case 'b':
224 busid = optarg; 230 busid = optarg;
225 break; 231 break;
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index d5ce34a410e7..f1b38e866dd7 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -30,6 +33,10 @@
30#include <netdb.h> 33#include <netdb.h>
31#include <unistd.h> 34#include <unistd.h>
32 35
36#include <dirent.h>
37
38#include <linux/usb/ch9.h>
39
33#include "usbip_common.h" 40#include "usbip_common.h"
34#include "usbip_network.h" 41#include "usbip_network.h"
35#include "usbip.h" 42#include "usbip.h"
@@ -205,8 +212,10 @@ static int list_devices(bool parsable)
205 /* Get device information. */ 212 /* Get device information. */
206 idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 213 idVendor = udev_device_get_sysattr_value(dev, "idVendor");
207 idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 214 idProduct = udev_device_get_sysattr_value(dev, "idProduct");
208 bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue"); 215 bConfValue = udev_device_get_sysattr_value(dev,
209 bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces"); 216 "bConfigurationValue");
217 bNumIntfs = udev_device_get_sysattr_value(dev,
218 "bNumInterfaces");
210 busid = udev_device_get_sysname(dev); 219 busid = udev_device_get_sysname(dev);
211 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 220 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
212 err("problem getting device attributes: %s", 221 err("problem getting device attributes: %s",
@@ -237,12 +246,90 @@ err_out:
237 return ret; 246 return ret;
238} 247}
239 248
249static int list_gadget_devices(bool parsable)
250{
251 int ret = -1;
252 struct udev *udev;
253 struct udev_enumerate *enumerate;
254 struct udev_list_entry *devices, *dev_list_entry;
255 struct udev_device *dev;
256 const char *path;
257 const char *driver;
258
259 const struct usb_device_descriptor *d_desc;
260 const char *descriptors;
261 char product_name[128];
262
263 uint16_t idVendor;
264 char idVendor_buf[8];
265 uint16_t idProduct;
266 char idProduct_buf[8];
267 const char *busid;
268
269 udev = udev_new();
270 enumerate = udev_enumerate_new(udev);
271
272 udev_enumerate_add_match_subsystem(enumerate, "platform");
273
274 udev_enumerate_scan_devices(enumerate);
275 devices = udev_enumerate_get_list_entry(enumerate);
276
277 udev_list_entry_foreach(dev_list_entry, devices) {
278 path = udev_list_entry_get_name(dev_list_entry);
279 dev = udev_device_new_from_syspath(udev, path);
280
281 driver = udev_device_get_driver(dev);
282 /* We only have mechanism to enumerate gadgets bound to vudc */
283 if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))
284 continue;
285
286 /* Get device information. */
287 descriptors = udev_device_get_sysattr_value(dev,
288 VUDC_DEVICE_DESCR_FILE);
289
290 if (!descriptors) {
291 err("problem getting device attributes: %s",
292 strerror(errno));
293 goto err_out;
294 }
295
296 d_desc = (const struct usb_device_descriptor *) descriptors;
297
298 idVendor = le16toh(d_desc->idVendor);
299 sprintf(idVendor_buf, "0x%4x", idVendor);
300 idProduct = le16toh(d_desc->idProduct);
301 sprintf(idProduct_buf, "0x%4x", idVendor);
302 busid = udev_device_get_sysname(dev);
303
304 /* Get product name. */
305 usbip_names_get_product(product_name, sizeof(product_name),
306 le16toh(idVendor),
307 le16toh(idProduct));
308
309 /* Print information. */
310 print_device(busid, idVendor_buf, idProduct_buf, parsable);
311 print_product_name(product_name, parsable);
312
313 printf("\n");
314
315 udev_device_unref(dev);
316 }
317 ret = 0;
318
319err_out:
320 udev_enumerate_unref(enumerate);
321 udev_unref(udev);
322
323 return ret;
324}
325
240int usbip_list(int argc, char *argv[]) 326int usbip_list(int argc, char *argv[])
241{ 327{
242 static const struct option opts[] = { 328 static const struct option opts[] = {
243 { "parsable", no_argument, NULL, 'p' }, 329 { "parsable", no_argument, NULL, 'p' },
244 { "remote", required_argument, NULL, 'r' }, 330 { "remote", required_argument, NULL, 'r' },
245 { "local", no_argument, NULL, 'l' }, 331 { "local", no_argument, NULL, 'l' },
332 { "device", no_argument, NULL, 'd' },
246 { NULL, 0, NULL, 0 } 333 { NULL, 0, NULL, 0 }
247 }; 334 };
248 335
@@ -254,7 +341,7 @@ int usbip_list(int argc, char *argv[])
254 err("failed to open %s", USBIDS_FILE); 341 err("failed to open %s", USBIDS_FILE);
255 342
256 for (;;) { 343 for (;;) {
257 opt = getopt_long(argc, argv, "pr:l", opts, NULL); 344 opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
258 345
259 if (opt == -1) 346 if (opt == -1)
260 break; 347 break;
@@ -269,6 +356,9 @@ int usbip_list(int argc, char *argv[])
269 case 'l': 356 case 'l':
270 ret = list_devices(parsable); 357 ret = list_devices(parsable);
271 goto out; 358 goto out;
359 case 'd':
360 ret = list_gadget_devices(parsable);
361 goto out;
272 default: 362 default:
273 goto err_out; 363 goto err_out;
274 } 364 }
diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip_port.c
index a2e884fd9226..7bd74fb3a9cd 100644
--- a/tools/usb/usbip/src/usbip_port.c
+++ b/tools/usb/usbip/src/usbip_port.c
@@ -22,10 +22,13 @@ static int list_imported_devices(void)
22 struct usbip_imported_device *idev; 22 struct usbip_imported_device *idev;
23 int ret; 23 int ret;
24 24
25 if (usbip_names_init(USBIDS_FILE))
26 err("failed to open %s", USBIDS_FILE);
27
25 ret = usbip_vhci_driver_open(); 28 ret = usbip_vhci_driver_open();
26 if (ret < 0) { 29 if (ret < 0) {
27 err("open vhci_driver"); 30 err("open vhci_driver");
28 return -1; 31 goto err_names_free;
29 } 32 }
30 33
31 printf("Imported USB devices\n"); 34 printf("Imported USB devices\n");
@@ -35,13 +38,19 @@ static int list_imported_devices(void)
35 idev = &vhci_driver->idev[i]; 38 idev = &vhci_driver->idev[i];
36 39
37 if (usbip_vhci_imported_device_dump(idev) < 0) 40 if (usbip_vhci_imported_device_dump(idev) < 0)
38 ret = -1; 41 goto err_driver_close;
39 } 42 }
40 43
41 usbip_vhci_driver_close(); 44 usbip_vhci_driver_close();
45 usbip_names_free();
42 46
43 return ret; 47 return ret;
44 48
49err_driver_close:
50 usbip_vhci_driver_close();
51err_names_free:
52 usbip_names_free();
53 return -1;
45} 54}
46 55
47int usbip_port_show(__attribute__((unused)) int argc, 56int usbip_port_show(__attribute__((unused)) int argc,
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index 2a7cd2b8d966..a0972dea9e6c 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -41,6 +44,8 @@
41#include <poll.h> 44#include <poll.h>
42 45
43#include "usbip_host_driver.h" 46#include "usbip_host_driver.h"
47#include "usbip_host_common.h"
48#include "usbip_device_driver.h"
44#include "usbip_common.h" 49#include "usbip_common.h"
45#include "usbip_network.h" 50#include "usbip_network.h"
46#include "list.h" 51#include "list.h"
@@ -64,6 +69,11 @@ static const char usbipd_help_string[] =
64 " -6, --ipv6\n" 69 " -6, --ipv6\n"
65 " Bind to IPv6. Default is both.\n" 70 " Bind to IPv6. Default is both.\n"
66 "\n" 71 "\n"
72 " -e, --device\n"
73 " Run in device mode.\n"
74 " Rather than drive an attached device, create\n"
75 " a virtual UDC to bind gadgets to.\n"
76 "\n"
67 " -D, --daemon\n" 77 " -D, --daemon\n"
68 " Run as a daemon process.\n" 78 " Run as a daemon process.\n"
69 "\n" 79 "\n"
@@ -83,6 +93,8 @@ static const char usbipd_help_string[] =
83 " -v, --version\n" 93 " -v, --version\n"
84 " Show version.\n"; 94 " Show version.\n";
85 95
96static struct usbip_host_driver *driver;
97
86static void usbipd_help(void) 98static void usbipd_help(void)
87{ 99{
88 printf("%s\n", usbipd_help_string); 100 printf("%s\n", usbipd_help_string);
@@ -107,7 +119,7 @@ static int recv_request_import(int sockfd)
107 } 119 }
108 PACK_OP_IMPORT_REQUEST(0, &req); 120 PACK_OP_IMPORT_REQUEST(0, &req);
109 121
110 list_for_each(i, &host_driver->edev_list) { 122 list_for_each(i, &driver->edev_list) {
111 edev = list_entry(i, struct usbip_exported_device, node); 123 edev = list_entry(i, struct usbip_exported_device, node);
112 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { 124 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
113 info("found requested device: %s", req.busid); 125 info("found requested device: %s", req.busid);
@@ -121,7 +133,7 @@ static int recv_request_import(int sockfd)
121 usbip_net_set_nodelay(sockfd); 133 usbip_net_set_nodelay(sockfd);
122 134
123 /* export device needs a TCP/IP socket descriptor */ 135 /* export device needs a TCP/IP socket descriptor */
124 rc = usbip_host_export_device(edev, sockfd); 136 rc = usbip_export_device(edev, sockfd);
125 if (rc < 0) 137 if (rc < 0)
126 error = 1; 138 error = 1;
127 } else { 139 } else {
@@ -166,7 +178,7 @@ static int send_reply_devlist(int connfd)
166 178
167 reply.ndev = 0; 179 reply.ndev = 0;
168 /* number of exported devices */ 180 /* number of exported devices */
169 list_for_each(j, &host_driver->edev_list) { 181 list_for_each(j, &driver->edev_list) {
170 reply.ndev += 1; 182 reply.ndev += 1;
171 } 183 }
172 info("exportable devices: %d", reply.ndev); 184 info("exportable devices: %d", reply.ndev);
@@ -184,7 +196,7 @@ static int send_reply_devlist(int connfd)
184 return -1; 196 return -1;
185 } 197 }
186 198
187 list_for_each(j, &host_driver->edev_list) { 199 list_for_each(j, &driver->edev_list) {
188 edev = list_entry(j, struct usbip_exported_device, node); 200 edev = list_entry(j, struct usbip_exported_device, node);
189 dump_usb_device(&edev->udev); 201 dump_usb_device(&edev->udev);
190 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); 202 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
@@ -246,7 +258,7 @@ static int recv_pdu(int connfd)
246 return -1; 258 return -1;
247 } 259 }
248 260
249 ret = usbip_host_refresh_device_list(); 261 ret = usbip_refresh_device_list(driver);
250 if (ret < 0) { 262 if (ret < 0) {
251 dbg("could not refresh device list: %d", ret); 263 dbg("could not refresh device list: %d", ret);
252 return -1; 264 return -1;
@@ -491,16 +503,13 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
491 struct timespec timeout; 503 struct timespec timeout;
492 sigset_t sigmask; 504 sigset_t sigmask;
493 505
494 if (usbip_host_driver_open()) { 506 if (usbip_driver_open(driver))
495 err("please load " USBIP_CORE_MOD_NAME ".ko and "
496 USBIP_HOST_DRV_NAME ".ko!");
497 return -1; 507 return -1;
498 }
499 508
500 if (daemonize) { 509 if (daemonize) {
501 if (daemon(0, 0) < 0) { 510 if (daemon(0, 0) < 0) {
502 err("daemonizing failed: %s", strerror(errno)); 511 err("daemonizing failed: %s", strerror(errno));
503 usbip_host_driver_close(); 512 usbip_driver_close(driver);
504 return -1; 513 return -1;
505 } 514 }
506 umask(0); 515 umask(0);
@@ -525,7 +534,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
525 534
526 ai_head = do_getaddrinfo(NULL, family); 535 ai_head = do_getaddrinfo(NULL, family);
527 if (!ai_head) { 536 if (!ai_head) {
528 usbip_host_driver_close(); 537 usbip_driver_close(driver);
529 return -1; 538 return -1;
530 } 539 }
531 nsockfd = listen_all_addrinfo(ai_head, sockfdlist, 540 nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
@@ -533,7 +542,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
533 freeaddrinfo(ai_head); 542 freeaddrinfo(ai_head);
534 if (nsockfd <= 0) { 543 if (nsockfd <= 0) {
535 err("failed to open a listening socket"); 544 err("failed to open a listening socket");
536 usbip_host_driver_close(); 545 usbip_driver_close(driver);
537 return -1; 546 return -1;
538 } 547 }
539 548
@@ -574,7 +583,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
574 583
575 info("shutting down " PROGNAME); 584 info("shutting down " PROGNAME);
576 free(fds); 585 free(fds);
577 usbip_host_driver_close(); 586 usbip_driver_close(driver);
578 587
579 return 0; 588 return 0;
580} 589}
@@ -587,6 +596,7 @@ int main(int argc, char *argv[])
587 { "daemon", no_argument, NULL, 'D' }, 596 { "daemon", no_argument, NULL, 'D' },
588 { "daemon", no_argument, NULL, 'D' }, 597 { "daemon", no_argument, NULL, 'D' },
589 { "debug", no_argument, NULL, 'd' }, 598 { "debug", no_argument, NULL, 'd' },
599 { "device", no_argument, NULL, 'e' },
590 { "pid", optional_argument, NULL, 'P' }, 600 { "pid", optional_argument, NULL, 'P' },
591 { "tcp-port", required_argument, NULL, 't' }, 601 { "tcp-port", required_argument, NULL, 't' },
592 { "help", no_argument, NULL, 'h' }, 602 { "help", no_argument, NULL, 'h' },
@@ -613,8 +623,9 @@ int main(int argc, char *argv[])
613 err("not running as root?"); 623 err("not running as root?");
614 624
615 cmd = cmd_standalone_mode; 625 cmd = cmd_standalone_mode;
626 driver = &host_driver;
616 for (;;) { 627 for (;;) {
617 opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL); 628 opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL);
618 629
619 if (opt == -1) 630 if (opt == -1)
620 break; 631 break;
@@ -644,6 +655,9 @@ int main(int argc, char *argv[])
644 case 'v': 655 case 'v':
645 cmd = cmd_version; 656 cmd = cmd_version;
646 break; 657 break;
658 case 'e':
659 driver = &device_driver;
660 break;
647 case '?': 661 case '?':
648 usbipd_help(); 662 usbipd_help();
649 default: 663 default:
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index feaa64ac4630..6ba745529833 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,6 +1,6 @@
1all: 1all:
2 2
3all: ring virtio_ring_0_9 virtio_ring_poll 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb
@@ -10,13 +10,16 @@ main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
11virtio_ring_0_9.o: virtio_ring_0_9.c main.h 11virtio_ring_0_9.o: virtio_ring_0_9.c main.h
12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h 12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
13virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
13ring: ring.o main.o 14ring: ring.o main.o
14virtio_ring_0_9: virtio_ring_0_9.o main.o 15virtio_ring_0_9: virtio_ring_0_9.o main.o
15virtio_ring_poll: virtio_ring_poll.o main.o 16virtio_ring_poll: virtio_ring_poll.o main.o
17virtio_ring_inorder: virtio_ring_inorder.o main.o
16clean: 18clean:
17 -rm main.o 19 -rm main.o
18 -rm ring.o ring 20 -rm ring.o ring
19 -rm virtio_ring_0_9.o virtio_ring_0_9 21 -rm virtio_ring_0_9.o virtio_ring_0_9
20 -rm virtio_ring_poll.o virtio_ring_poll 22 -rm virtio_ring_poll.o virtio_ring_poll
23 -rm virtio_ring_inorder.o virtio_ring_inorder
21 24
22.PHONY: all clean 25.PHONY: all clean
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c
index 3a5ff438bd62..147abb452a6c 100644
--- a/tools/virtio/ringtest/main.c
+++ b/tools/virtio/ringtest/main.c
@@ -115,7 +115,7 @@ static void run_guest(void)
115 do { 115 do {
116 if (started < bufs && 116 if (started < bufs &&
117 started - completed < max_outstanding) { 117 started - completed < max_outstanding) {
118 r = add_inbuf(0, NULL, "Hello, world!"); 118 r = add_inbuf(0, "Buffer\n", "Hello, world!");
119 if (__builtin_expect(r == 0, true)) { 119 if (__builtin_expect(r == 0, true)) {
120 ++started; 120 ++started;
121 if (!--tokick) { 121 if (!--tokick) {
diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c
index 47c9a1a18d36..761866212aac 100644
--- a/tools/virtio/ringtest/virtio_ring_0_9.c
+++ b/tools/virtio/ringtest/virtio_ring_0_9.c
@@ -26,6 +26,14 @@ struct vring ring;
26 * high bits of ring id ^ 0x8000). 26 * high bits of ring id ^ 0x8000).
27 */ 27 */
28/* #ifdef RING_POLL */ 28/* #ifdef RING_POLL */
29/* enabling the below activates experimental in-order code
30 * (which skips ring updates and reads and writes len in descriptor).
31 */
32/* #ifdef INORDER */
33
34#if defined(RING_POLL) && defined(INORDER)
35#error "RING_POLL and INORDER are mutually exclusive"
36#endif
29 37
30/* how much padding is needed to avoid false cache sharing */ 38/* how much padding is needed to avoid false cache sharing */
31#define HOST_GUEST_PADDING 0x80 39#define HOST_GUEST_PADDING 0x80
@@ -35,7 +43,11 @@ struct guest {
35 unsigned short last_used_idx; 43 unsigned short last_used_idx;
36 unsigned short num_free; 44 unsigned short num_free;
37 unsigned short kicked_avail_idx; 45 unsigned short kicked_avail_idx;
46#ifndef INORDER
38 unsigned short free_head; 47 unsigned short free_head;
48#else
49 unsigned short reserved_free_head;
50#endif
39 unsigned char reserved[HOST_GUEST_PADDING - 10]; 51 unsigned char reserved[HOST_GUEST_PADDING - 10];
40} guest; 52} guest;
41 53
@@ -66,8 +78,10 @@ void alloc_ring(void)
66 guest.avail_idx = 0; 78 guest.avail_idx = 0;
67 guest.kicked_avail_idx = -1; 79 guest.kicked_avail_idx = -1;
68 guest.last_used_idx = 0; 80 guest.last_used_idx = 0;
81#ifndef INORDER
69 /* Put everything in free lists. */ 82 /* Put everything in free lists. */
70 guest.free_head = 0; 83 guest.free_head = 0;
84#endif
71 for (i = 0; i < ring_size - 1; i++) 85 for (i = 0; i < ring_size - 1; i++)
72 ring.desc[i].next = i + 1; 86 ring.desc[i].next = i + 1;
73 host.used_idx = 0; 87 host.used_idx = 0;
@@ -84,13 +98,20 @@ void alloc_ring(void)
84/* guest side */ 98/* guest side */
85int add_inbuf(unsigned len, void *buf, void *datap) 99int add_inbuf(unsigned len, void *buf, void *datap)
86{ 100{
87 unsigned head, avail; 101 unsigned head;
102#ifndef INORDER
103 unsigned avail;
104#endif
88 struct vring_desc *desc; 105 struct vring_desc *desc;
89 106
90 if (!guest.num_free) 107 if (!guest.num_free)
91 return -1; 108 return -1;
92 109
110#ifdef INORDER
111 head = (ring_size - 1) & (guest.avail_idx++);
112#else
93 head = guest.free_head; 113 head = guest.free_head;
114#endif
94 guest.num_free--; 115 guest.num_free--;
95 116
96 desc = ring.desc; 117 desc = ring.desc;
@@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
102 * descriptors. 123 * descriptors.
103 */ 124 */
104 desc[head].flags &= ~VRING_DESC_F_NEXT; 125 desc[head].flags &= ~VRING_DESC_F_NEXT;
126#ifndef INORDER
105 guest.free_head = desc[head].next; 127 guest.free_head = desc[head].next;
128#endif
106 129
107 data[head].data = datap; 130 data[head].data = datap;
108 131
@@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
113 ring.avail->ring[avail & (ring_size - 1)] = 136 ring.avail->ring[avail & (ring_size - 1)] =
114 (head | (avail & ~(ring_size - 1))) ^ 0x8000; 137 (head | (avail & ~(ring_size - 1))) ^ 0x8000;
115#else 138#else
139#ifndef INORDER
140 /* Barrier A (for pairing) */
141 smp_release();
116 avail = (ring_size - 1) & (guest.avail_idx++); 142 avail = (ring_size - 1) & (guest.avail_idx++);
117 ring.avail->ring[avail] = head; 143 ring.avail->ring[avail] = head;
144#endif
118 /* Barrier A (for pairing) */ 145 /* Barrier A (for pairing) */
119 smp_release(); 146 smp_release();
120#endif 147#endif
@@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
141 return NULL; 168 return NULL;
142 /* Barrier B (for pairing) */ 169 /* Barrier B (for pairing) */
143 smp_acquire(); 170 smp_acquire();
171#ifdef INORDER
172 head = (ring_size - 1) & guest.last_used_idx;
173 index = head;
174#else
144 head = (ring_size - 1) & guest.last_used_idx; 175 head = (ring_size - 1) & guest.last_used_idx;
145 index = ring.used->ring[head].id; 176 index = ring.used->ring[head].id;
146#endif 177#endif
178
179#endif
180#ifdef INORDER
181 *lenp = ring.desc[index].len;
182#else
147 *lenp = ring.used->ring[head].len; 183 *lenp = ring.used->ring[head].len;
184#endif
148 datap = data[index].data; 185 datap = data[index].data;
149 *bufp = (void*)(unsigned long)ring.desc[index].addr; 186 *bufp = (void*)(unsigned long)ring.desc[index].addr;
150 data[index].data = NULL; 187 data[index].data = NULL;
188#ifndef INORDER
151 ring.desc[index].next = guest.free_head; 189 ring.desc[index].next = guest.free_head;
152 guest.free_head = index; 190 guest.free_head = index;
191#endif
153 guest.num_free++; 192 guest.num_free++;
154 guest.last_used_idx++; 193 guest.last_used_idx++;
155 return datap; 194 return datap;
@@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
283 smp_acquire(); 322 smp_acquire();
284 323
285 used_idx &= ring_size - 1; 324 used_idx &= ring_size - 1;
325#ifdef INORDER
326 head = used_idx;
327#else
286 head = ring.avail->ring[used_idx]; 328 head = ring.avail->ring[used_idx];
329#endif
287 desc = &ring.desc[head]; 330 desc = &ring.desc[head];
288#endif 331#endif
289 332
290 *lenp = desc->len; 333 *lenp = desc->len;
291 *bufp = (void *)(unsigned long)desc->addr; 334 *bufp = (void *)(unsigned long)desc->addr;
292 335
336#ifdef INORDER
337 desc->len = desc->len - 1;
338#else
293 /* now update used ring */ 339 /* now update used ring */
294 ring.used->ring[used_idx].id = head; 340 ring.used->ring[used_idx].id = head;
295 ring.used->ring[used_idx].len = desc->len - 1; 341 ring.used->ring[used_idx].len = desc->len - 1;
342#endif
296 /* Barrier B (for pairing) */ 343 /* Barrier B (for pairing) */
297 smp_release(); 344 smp_release();
298 host.used_idx++; 345 host.used_idx++;
diff --git a/tools/virtio/ringtest/virtio_ring_inorder.c b/tools/virtio/ringtest/virtio_ring_inorder.c
new file mode 100644
index 000000000000..2438ca58a2ad
--- /dev/null
+++ b/tools/virtio/ringtest/virtio_ring_inorder.c
@@ -0,0 +1,2 @@
1#define INORDER 1
2#include "virtio_ring_0_9.c"