aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 13:49:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-06 13:49:42 -0400
commit39eda2aba6be642b71f2e0ad623dcb09fd9d79cf (patch)
treecd0c8f547847641af73e38aab2478f3119dee490 /tools
parent2e515bf096c245ba87f20ab4b4ea20f911afaeda (diff)
parent9f24b0c9ef9b6b1292579c9e2cd7ff07ddc372b7 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Ben Herrenschmidt: "Here's the powerpc batch for this merge window. Some of the highlights are: - A bunch of endian fixes ! We don't have full LE support yet in that release but this contains a lot of fixes all over arch/powerpc to use the proper accessors, call the firmware with the right endian mode, etc... - A few updates to our "powernv" platform (non-virtualized, the one to run KVM on), among other, support for bridging the P8 LPC bus for UARTs, support and some EEH fixes. - Some mpc51xx clock API cleanups in preparation for a clock API overhaul - A pile of cleanups of our old math emulation code, including better support for using it to emulate optional FP instructions on embedded chips that otherwise have a HW FPU. - Some infrastructure in selftest, for powerpc now, but could be generalized, initially used by some tests for our perf instruction counting code. - A pile of fixes for hotplug on pseries (that was seriously bitrotting) - The usual slew of freescale embedded updates, new boards, 64-bit hiberation support, e6500 core PMU support, etc..." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (146 commits) powerpc: Correct FSCR bit definitions powerpc/xmon: Fix printing of set of CPUs in xmon powerpc/pseries: Move lparcfg.c to platforms/pseries powerpc/powernv: Return secondary CPUs to firmware on kexec powerpc/btext: Fix CONFIG_PPC_EARLY_DEBUG_BOOTX on ppc32 powerpc: Cleanup handling of the DSCR bit in the FSCR register powerpc/pseries: Child nodes are not detached by dlpar_detach_node powerpc/pseries: Add mising of_node_put in delete_dt_node powerpc/pseries: Make dlpar_configure_connector parent node aware powerpc/pseries: Do all node initialization in dlpar_parse_cc_node powerpc/pseries: Fix parsing of initial node path in update_dt_node powerpc/pseries: Pack update_props_workarea to map correctly to rtas buffer header powerpc/pseries: Fix over writing of rtas return code in update_dt_node powerpc/pseries: Fix creation of loop in device node property list powerpc: Skip emulating & leave interrupts off for kernel program checks powerpc: Add more exception trampolines for hypervisor exceptions powerpc: Fix location and rename exception trampolines powerpc: Add more trap names to xmon powerpc/pseries: Add a warning in the case of cross-cpu VPA registration powerpc: Update the 00-Index in Documentation/powerpc ...
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/Makefile39
-rw-r--r--tools/testing/selftests/powerpc/harness.c105
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile23
-rw-r--r--tools/testing/selftests/powerpc/pmu/count_instructions.c135
-rw-r--r--tools/testing/selftests/powerpc/pmu/event.c105
-rw-r--r--tools/testing/selftests/powerpc/pmu/event.h39
-rw-r--r--tools/testing/selftests/powerpc/pmu/loop.S46
-rw-r--r--tools/testing/selftests/powerpc/subunit.h47
-rw-r--r--tools/testing/selftests/powerpc/utils.h34
10 files changed, 574 insertions, 0 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4cb14cae3791..9f3eae290900 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -8,6 +8,7 @@ TARGETS += net
8TARGETS += ptrace 8TARGETS += ptrace
9TARGETS += timers 9TARGETS += timers
10TARGETS += vm 10TARGETS += vm
11TARGETS += powerpc
11 12
12all: 13all:
13 for TARGET in $(TARGETS); do \ 14 for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
new file mode 100644
index 000000000000..bd24ae5aaeab
--- /dev/null
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -0,0 +1,39 @@
1# Makefile for powerpc selftests
2
3# ARCH can be overridden by the user for cross compiling
4ARCH ?= $(shell uname -m)
5ARCH := $(shell echo $(ARCH) | sed -e s/ppc.*/powerpc/)
6
7ifeq ($(ARCH),powerpc)
8
9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
10
11CC := $(CROSS_COMPILE)$(CC)
12CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
13
14export CC CFLAGS
15
16TARGETS = pmu
17
18endif
19
20all:
21 @for TARGET in $(TARGETS); do \
22 $(MAKE) -C $$TARGET all; \
23 done;
24
25run_tests: all
26 @for TARGET in $(TARGETS); do \
27 $(MAKE) -C $$TARGET run_tests; \
28 done;
29
30clean:
31 @for TARGET in $(TARGETS); do \
32 $(MAKE) -C $$TARGET clean; \
33 done;
34 rm -f tags
35
36tags:
37 find . -name '*.c' -o -name '*.h' | xargs ctags
38
39.PHONY: all run_tests clean tags
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
new file mode 100644
index 000000000000..e80c42a584fe
--- /dev/null
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <errno.h>
7#include <signal.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <sys/types.h>
12#include <sys/wait.h>
13#include <unistd.h>
14
15#include "subunit.h"
16#include "utils.h"
17
18#define TIMEOUT 120
19#define KILL_TIMEOUT 5
20
21
22int run_test(int (test_function)(void), char *name)
23{
24 bool terminated;
25 int rc, status;
26 pid_t pid;
27
28 /* Make sure output is flushed before forking */
29 fflush(stdout);
30
31 pid = fork();
32 if (pid == 0) {
33 exit(test_function());
34 } else if (pid == -1) {
35 perror("fork");
36 return 1;
37 }
38
39 /* Wake us up in timeout seconds */
40 alarm(TIMEOUT);
41 terminated = false;
42
43wait:
44 rc = waitpid(pid, &status, 0);
45 if (rc == -1) {
46 if (errno != EINTR) {
47 printf("unknown error from waitpid\n");
48 return 1;
49 }
50
51 if (terminated) {
52 printf("!! force killing %s\n", name);
53 kill(pid, SIGKILL);
54 return 1;
55 } else {
56 printf("!! killing %s\n", name);
57 kill(pid, SIGTERM);
58 terminated = true;
59 alarm(KILL_TIMEOUT);
60 goto wait;
61 }
62 }
63
64 if (WIFEXITED(status))
65 status = WEXITSTATUS(status);
66 else {
67 if (WIFSIGNALED(status))
68 printf("!! child died by signal %d\n", WTERMSIG(status));
69 else
70 printf("!! child died by unknown cause\n");
71
72 status = 1; /* Signal or other */
73 }
74
75 return status;
76}
77
78static void alarm_handler(int signum)
79{
80 /* Jut wake us up from waitpid */
81}
82
83static struct sigaction alarm_action = {
84 .sa_handler = alarm_handler,
85};
86
87int test_harness(int (test_function)(void), char *name)
88{
89 int rc;
90
91 test_start(name);
92 test_set_git_version(GIT_VERSION);
93
94 if (sigaction(SIGALRM, &alarm_action, NULL)) {
95 perror("sigaction");
96 test_error(name);
97 return 1;
98 }
99
100 rc = run_test(test_function, name);
101
102 test_finish(name, rc);
103
104 return rc;
105}
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
new file mode 100644
index 000000000000..7216f0091655
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -0,0 +1,23 @@
1noarg:
2 $(MAKE) -C ../
3
4PROGS := count_instructions
5EXTRA_SOURCES := ../harness.c event.c
6
7all: $(PROGS)
8
9$(PROGS): $(EXTRA_SOURCES)
10
11# loop.S can only be built 64-bit
12count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
13 $(CC) $(CFLAGS) -m64 -o $@ $^
14
15run_tests: all
16 @-for PROG in $(PROGS); do \
17 ./$$PROG; \
18 done;
19
20clean:
21 rm -f $(PROGS) loop.o
22
23.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/pmu/count_instructions.c b/tools/testing/selftests/powerpc/pmu/count_instructions.c
new file mode 100644
index 000000000000..312b4f0fd27c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/count_instructions.c
@@ -0,0 +1,135 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE
7
8#include <stdio.h>
9#include <stdbool.h>
10#include <string.h>
11#include <sys/prctl.h>
12
13#include "event.h"
14#include "utils.h"
15
16extern void thirty_two_instruction_loop(u64 loops);
17
18static void setup_event(struct event *e, u64 config, char *name)
19{
20 event_init_opts(e, config, PERF_TYPE_HARDWARE, name);
21
22 e->attr.disabled = 1;
23 e->attr.exclude_kernel = 1;
24 e->attr.exclude_hv = 1;
25 e->attr.exclude_idle = 1;
26}
27
28static int do_count_loop(struct event *events, u64 instructions,
29 u64 overhead, bool report)
30{
31 s64 difference, expected;
32 double percentage;
33
34 prctl(PR_TASK_PERF_EVENTS_ENABLE);
35
36 /* Run for 1M instructions */
37 thirty_two_instruction_loop(instructions >> 5);
38
39 prctl(PR_TASK_PERF_EVENTS_DISABLE);
40
41 event_read(&events[0]);
42 event_read(&events[1]);
43
44 expected = instructions + overhead;
45 difference = events[0].result.value - expected;
46 percentage = (double)difference / events[0].result.value * 100;
47
48 if (report) {
49 event_report(&events[0]);
50 event_report(&events[1]);
51
52 printf("Looped for %llu instructions, overhead %llu\n", instructions, overhead);
53 printf("Expected %llu\n", expected);
54 printf("Actual %llu\n", events[0].result.value);
55 printf("Delta %lld, %f%%\n", difference, percentage);
56 }
57
58 event_reset(&events[0]);
59 event_reset(&events[1]);
60
61 if (difference < 0)
62 difference = -difference;
63
64 /* Tolerate a difference below 0.0001 % */
65 difference *= 10000 * 100;
66 if (difference / events[0].result.value)
67 return -1;
68
69 return 0;
70}
71
72/* Count how many instructions it takes to do a null loop */
73static u64 determine_overhead(struct event *events)
74{
75 u64 current, overhead;
76 int i;
77
78 do_count_loop(events, 0, 0, false);
79 overhead = events[0].result.value;
80
81 for (i = 0; i < 100; i++) {
82 do_count_loop(events, 0, 0, false);
83 current = events[0].result.value;
84 if (current < overhead) {
85 printf("Replacing overhead %llu with %llu\n", overhead, current);
86 overhead = current;
87 }
88 }
89
90 return overhead;
91}
92
93static int count_instructions(void)
94{
95 struct event events[2];
96 u64 overhead;
97
98 setup_event(&events[0], PERF_COUNT_HW_INSTRUCTIONS, "instructions");
99 setup_event(&events[1], PERF_COUNT_HW_CPU_CYCLES, "cycles");
100
101 if (event_open(&events[0])) {
102 perror("perf_event_open");
103 return -1;
104 }
105
106 if (event_open_with_group(&events[1], events[0].fd)) {
107 perror("perf_event_open");
108 return -1;
109 }
110
111 overhead = determine_overhead(events);
112 printf("Overhead of null loop: %llu instructions\n", overhead);
113
114 /* Run for 1M instructions */
115 FAIL_IF(do_count_loop(events, 0x100000, overhead, true));
116
117 /* Run for 10M instructions */
118 FAIL_IF(do_count_loop(events, 0xa00000, overhead, true));
119
120 /* Run for 100M instructions */
121 FAIL_IF(do_count_loop(events, 0x6400000, overhead, true));
122
123 /* Run for 1G instructions */
124 FAIL_IF(do_count_loop(events, 0x40000000, overhead, true));
125
126 event_close(&events[0]);
127 event_close(&events[1]);
128
129 return 0;
130}
131
132int main(void)
133{
134 return test_harness(count_instructions, "count_instructions");
135}
diff --git a/tools/testing/selftests/powerpc/pmu/event.c b/tools/testing/selftests/powerpc/pmu/event.c
new file mode 100644
index 000000000000..2b2d11df2450
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE
7#include <unistd.h>
8#include <sys/syscall.h>
9#include <string.h>
10#include <stdio.h>
11#include <sys/ioctl.h>
12
13#include "event.h"
14
15
16int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
17 int group_fd, unsigned long flags)
18{
19 return syscall(__NR_perf_event_open, attr, pid, cpu,
20 group_fd, flags);
21}
22
23void event_init_opts(struct event *e, u64 config, int type, char *name)
24{
25 memset(e, 0, sizeof(*e));
26
27 e->name = name;
28
29 e->attr.type = type;
30 e->attr.config = config;
31 e->attr.size = sizeof(e->attr);
32 /* This has to match the structure layout in the header */
33 e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \
34 PERF_FORMAT_TOTAL_TIME_RUNNING;
35}
36
37void event_init_named(struct event *e, u64 config, char *name)
38{
39 event_init_opts(e, config, PERF_TYPE_RAW, name);
40}
41
42#define PERF_CURRENT_PID 0
43#define PERF_NO_CPU -1
44#define PERF_NO_GROUP -1
45
46int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd)
47{
48 e->fd = perf_event_open(&e->attr, pid, cpu, group_fd, 0);
49 if (e->fd == -1) {
50 perror("perf_event_open");
51 return -1;
52 }
53
54 return 0;
55}
56
57int event_open_with_group(struct event *e, int group_fd)
58{
59 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, group_fd);
60}
61
62int event_open(struct event *e)
63{
64 return event_open_with_options(e, PERF_CURRENT_PID, PERF_NO_CPU, PERF_NO_GROUP);
65}
66
67void event_close(struct event *e)
68{
69 close(e->fd);
70}
71
72int event_reset(struct event *e)
73{
74 return ioctl(e->fd, PERF_EVENT_IOC_RESET);
75}
76
77int event_read(struct event *e)
78{
79 int rc;
80
81 rc = read(e->fd, &e->result, sizeof(e->result));
82 if (rc != sizeof(e->result)) {
83 fprintf(stderr, "read error on event %p!\n", e);
84 return -1;
85 }
86
87 return 0;
88}
89
90void event_report_justified(struct event *e, int name_width, int result_width)
91{
92 printf("%*s: result %*llu ", name_width, e->name, result_width,
93 e->result.value);
94
95 if (e->result.running == e->result.enabled)
96 printf("running/enabled %llu\n", e->result.running);
97 else
98 printf("running %llu enabled %llu\n", e->result.running,
99 e->result.enabled);
100}
101
102void event_report(struct event *e)
103{
104 event_report_justified(e, 0, 0);
105}
diff --git a/tools/testing/selftests/powerpc/pmu/event.h b/tools/testing/selftests/powerpc/pmu/event.h
new file mode 100644
index 000000000000..e6993192ff34
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/event.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_PMU_EVENT_H
7#define _SELFTESTS_POWERPC_PMU_EVENT_H
8
9#include <unistd.h>
10#include <linux/perf_event.h>
11
12#include "utils.h"
13
14
15struct event {
16 struct perf_event_attr attr;
17 char *name;
18 int fd;
19 /* This must match the read_format we use */
20 struct {
21 u64 value;
22 u64 running;
23 u64 enabled;
24 } result;
25};
26
27void event_init(struct event *e, u64 config);
28void event_init_named(struct event *e, u64 config, char *name);
29void event_init_opts(struct event *e, u64 config, int type, char *name);
30int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd);
31int event_open_with_group(struct event *e, int group_fd);
32int event_open(struct event *e);
33void event_close(struct event *e);
34int event_reset(struct event *e);
35int event_read(struct event *e);
36void event_report_justified(struct event *e, int name_width, int result_width);
37void event_report(struct event *e);
38
39#endif /* _SELFTESTS_POWERPC_PMU_EVENT_H */
diff --git a/tools/testing/selftests/powerpc/pmu/loop.S b/tools/testing/selftests/powerpc/pmu/loop.S
new file mode 100644
index 000000000000..8820e3df1444
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/loop.S
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6 .text
7
8 .global thirty_two_instruction_loop
9 .type .thirty_two_instruction_loop,@function
10 .section ".opd","aw",@progbits
11thirty_two_instruction_loop:
12 .quad .thirty_two_instruction_loop, .TOC.@tocbase, 0
13 .previous
14.thirty_two_instruction_loop:
15 cmpwi %r3,0
16 beqlr
17 addi %r4,%r3,1
18 addi %r4,%r4,1
19 addi %r4,%r4,1
20 addi %r4,%r4,1
21 addi %r4,%r4,1
22 addi %r4,%r4,1
23 addi %r4,%r4,1
24 addi %r4,%r4,1
25 addi %r4,%r4,1
26 addi %r4,%r4,1
27 addi %r4,%r4,1
28 addi %r4,%r4,1
29 addi %r4,%r4,1
30 addi %r4,%r4,1
31 addi %r4,%r4,1
32 addi %r4,%r4,1
33 addi %r4,%r4,1
34 addi %r4,%r4,1
35 addi %r4,%r4,1
36 addi %r4,%r4,1
37 addi %r4,%r4,1
38 addi %r4,%r4,1
39 addi %r4,%r4,1
40 addi %r4,%r4,1
41 addi %r4,%r4,1
42 addi %r4,%r4,1
43 addi %r4,%r4,1
44 addi %r4,%r4,1 # 28 addi's
45 subi %r3,%r3,1
46 b .thirty_two_instruction_loop
diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h
new file mode 100644
index 000000000000..98a22920792d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/subunit.h
@@ -0,0 +1,47 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_SUBUNIT_H
7#define _SELFTESTS_POWERPC_SUBUNIT_H
8
9static inline void test_start(char *name)
10{
11 printf("test: %s\n", name);
12}
13
14static inline void test_failure_detail(char *name, char *detail)
15{
16 printf("failure: %s [%s]\n", name, detail);
17}
18
19static inline void test_failure(char *name)
20{
21 printf("failure: %s\n", name);
22}
23
24static inline void test_error(char *name)
25{
26 printf("error: %s\n", name);
27}
28
29static inline void test_success(char *name)
30{
31 printf("success: %s\n", name);
32}
33
34static inline void test_finish(char *name, int status)
35{
36 if (status)
37 test_failure(name);
38 else
39 test_success(name);
40}
41
42static inline void test_set_git_version(char *value)
43{
44 printf("tags: git_version:%s\n", value);
45}
46
47#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
new file mode 100644
index 000000000000..5851c4b0f553
--- /dev/null
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright 2013, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#ifndef _SELFTESTS_POWERPC_UTILS_H
7#define _SELFTESTS_POWERPC_UTILS_H
8
9#include <stdint.h>
10#include <stdbool.h>
11
12/* Avoid headaches with PRI?64 - just use %ll? always */
13typedef unsigned long long u64;
14typedef signed long long s64;
15
16/* Just for familiarity */
17typedef uint32_t u32;
18typedef uint8_t u8;
19
20
21int test_harness(int (test_function)(void), char *name);
22
23
24/* Yes, this is evil */
25#define FAIL_IF(x) \
26do { \
27 if ((x)) { \
28 fprintf(stderr, \
29 "[FAIL] Test FAILED on line %d\n", __LINE__); \
30 return 1; \
31 } \
32} while (0)
33
34#endif /* _SELFTESTS_POWERPC_UTILS_H */