diff options
Diffstat (limited to 'tools/testing/selftests/powerpc')
14 files changed, 393 insertions, 4 deletions
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index f6ff90a76bd7..1d5e7ad2c460 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile | |||
@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR | |||
13 | 13 | ||
14 | export CC CFLAGS | 14 | export CC CFLAGS |
15 | 15 | ||
16 | TARGETS = pmu copyloops mm tm primitives | 16 | TARGETS = pmu copyloops mm tm primitives stringloops |
17 | 17 | ||
18 | endif | 18 | endif |
19 | 19 | ||
diff --git a/tools/testing/selftests/powerpc/copyloops/.gitignore b/tools/testing/selftests/powerpc/copyloops/.gitignore new file mode 100644 index 000000000000..25a192f62c4d --- /dev/null +++ b/tools/testing/selftests/powerpc/copyloops/.gitignore | |||
@@ -0,0 +1,4 @@ | |||
1 | copyuser_64 | ||
2 | copyuser_power7 | ||
3 | memcpy_64 | ||
4 | memcpy_power7 | ||
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore new file mode 100644 index 000000000000..b43ade0ec861 --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | hugetlb_vs_thp_test | ||
2 | subpage_prot | ||
3 | tempfile | ||
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile index 357ccbd6bad9..a14c538dd7f8 100644 --- a/tools/testing/selftests/powerpc/mm/Makefile +++ b/tools/testing/selftests/powerpc/mm/Makefile | |||
@@ -1,9 +1,9 @@ | |||
1 | noarg: | 1 | noarg: |
2 | $(MAKE) -C ../ | 2 | $(MAKE) -C ../ |
3 | 3 | ||
4 | PROGS := hugetlb_vs_thp_test | 4 | PROGS := hugetlb_vs_thp_test subpage_prot |
5 | 5 | ||
6 | all: $(PROGS) | 6 | all: $(PROGS) tempfile |
7 | 7 | ||
8 | $(PROGS): ../harness.c | 8 | $(PROGS): ../harness.c |
9 | 9 | ||
@@ -12,7 +12,10 @@ run_tests: all | |||
12 | ./$$PROG; \ | 12 | ./$$PROG; \ |
13 | done; | 13 | done; |
14 | 14 | ||
15 | tempfile: | ||
16 | dd if=/dev/zero of=tempfile bs=64k count=1 | ||
17 | |||
15 | clean: | 18 | clean: |
16 | rm -f $(PROGS) | 19 | rm -f $(PROGS) tempfile |
17 | 20 | ||
18 | .PHONY: all run_tests clean | 21 | .PHONY: all run_tests clean |
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c new file mode 100644 index 000000000000..440180ff8089 --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
6 | * as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it would be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <assert.h> | ||
15 | #include <errno.h> | ||
16 | #include <fcntl.h> | ||
17 | #include <signal.h> | ||
18 | #include <stdarg.h> | ||
19 | #include <stdio.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <sys/mman.h> | ||
23 | #include <sys/ptrace.h> | ||
24 | #include <sys/syscall.h> | ||
25 | #include <ucontext.h> | ||
26 | #include <unistd.h> | ||
27 | |||
28 | #include "utils.h" | ||
29 | |||
30 | char *file_name; | ||
31 | |||
32 | int in_test; | ||
33 | volatile int faulted; | ||
34 | volatile void *dar; | ||
35 | int errors; | ||
36 | |||
37 | static void segv(int signum, siginfo_t *info, void *ctxt_v) | ||
38 | { | ||
39 | ucontext_t *ctxt = (ucontext_t *)ctxt_v; | ||
40 | struct pt_regs *regs = ctxt->uc_mcontext.regs; | ||
41 | |||
42 | if (!in_test) { | ||
43 | fprintf(stderr, "Segfault outside of test !\n"); | ||
44 | exit(1); | ||
45 | } | ||
46 | |||
47 | faulted = 1; | ||
48 | dar = (void *)regs->dar; | ||
49 | regs->nip += 4; | ||
50 | } | ||
51 | |||
52 | static inline void do_read(const volatile void *addr) | ||
53 | { | ||
54 | int ret; | ||
55 | |||
56 | asm volatile("lwz %0,0(%1); twi 0,%0,0; isync;\n" | ||
57 | : "=r" (ret) : "r" (addr) : "memory"); | ||
58 | } | ||
59 | |||
60 | static inline void do_write(const volatile void *addr) | ||
61 | { | ||
62 | int val = 0x1234567; | ||
63 | |||
64 | asm volatile("stw %0,0(%1); sync; \n" | ||
65 | : : "r" (val), "r" (addr) : "memory"); | ||
66 | } | ||
67 | |||
68 | static inline void check_faulted(void *addr, long page, long subpage, int write) | ||
69 | { | ||
70 | int want_fault = (subpage == ((page + 3) % 16)); | ||
71 | |||
72 | if (write) | ||
73 | want_fault |= (subpage == ((page + 1) % 16)); | ||
74 | |||
75 | if (faulted != want_fault) { | ||
76 | printf("Failed at 0x%p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n", | ||
77 | addr, page, subpage, write, | ||
78 | want_fault ? "fault" : "pass", | ||
79 | faulted ? "fault" : "pass"); | ||
80 | ++errors; | ||
81 | } | ||
82 | |||
83 | if (faulted) { | ||
84 | if (dar != addr) { | ||
85 | printf("Fault expected at 0x%p and happened at 0x%p !\n", | ||
86 | addr, dar); | ||
87 | } | ||
88 | faulted = 0; | ||
89 | asm volatile("sync" : : : "memory"); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static int run_test(void *addr, unsigned long size) | ||
94 | { | ||
95 | unsigned int *map; | ||
96 | long i, j, pages, err; | ||
97 | |||
98 | pages = size / 0x10000; | ||
99 | map = malloc(pages * 4); | ||
100 | assert(map); | ||
101 | |||
102 | /* | ||
103 | * for each page, mark subpage i % 16 read only and subpage | ||
104 | * (i + 3) % 16 inaccessible | ||
105 | */ | ||
106 | for (i = 0; i < pages; i++) { | ||
107 | map[i] = (0x40000000 >> (((i + 1) * 2) % 32)) | | ||
108 | (0xc0000000 >> (((i + 3) * 2) % 32)); | ||
109 | } | ||
110 | |||
111 | err = syscall(__NR_subpage_prot, addr, size, map); | ||
112 | if (err) { | ||
113 | perror("subpage_perm"); | ||
114 | return 1; | ||
115 | } | ||
116 | free(map); | ||
117 | |||
118 | in_test = 1; | ||
119 | errors = 0; | ||
120 | for (i = 0; i < pages; i++) { | ||
121 | for (j = 0; j < 16; j++, addr += 0x1000) { | ||
122 | do_read(addr); | ||
123 | check_faulted(addr, i, j, 0); | ||
124 | do_write(addr); | ||
125 | check_faulted(addr, i, j, 1); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | in_test = 0; | ||
130 | if (errors) { | ||
131 | printf("%d errors detected\n", errors); | ||
132 | return 1; | ||
133 | } | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | int test_anon(void) | ||
139 | { | ||
140 | unsigned long align; | ||
141 | struct sigaction act = { | ||
142 | .sa_sigaction = segv, | ||
143 | .sa_flags = SA_SIGINFO | ||
144 | }; | ||
145 | void *mallocblock; | ||
146 | unsigned long mallocsize; | ||
147 | |||
148 | if (getpagesize() != 0x10000) { | ||
149 | fprintf(stderr, "Kernel page size must be 64K!\n"); | ||
150 | return 1; | ||
151 | } | ||
152 | |||
153 | sigaction(SIGSEGV, &act, NULL); | ||
154 | |||
155 | mallocsize = 4 * 16 * 1024 * 1024; | ||
156 | |||
157 | FAIL_IF(posix_memalign(&mallocblock, 64 * 1024, mallocsize)); | ||
158 | |||
159 | align = (unsigned long)mallocblock; | ||
160 | if (align & 0xffff) | ||
161 | align = (align | 0xffff) + 1; | ||
162 | |||
163 | mallocblock = (void *)align; | ||
164 | |||
165 | printf("allocated malloc block of 0x%lx bytes at 0x%p\n", | ||
166 | mallocsize, mallocblock); | ||
167 | |||
168 | printf("testing malloc block...\n"); | ||
169 | |||
170 | return run_test(mallocblock, mallocsize); | ||
171 | } | ||
172 | |||
173 | int test_file(void) | ||
174 | { | ||
175 | struct sigaction act = { | ||
176 | .sa_sigaction = segv, | ||
177 | .sa_flags = SA_SIGINFO | ||
178 | }; | ||
179 | void *fileblock; | ||
180 | off_t filesize; | ||
181 | int fd; | ||
182 | |||
183 | fd = open(file_name, O_RDWR); | ||
184 | if (fd == -1) { | ||
185 | perror("failed to open file"); | ||
186 | return 1; | ||
187 | } | ||
188 | sigaction(SIGSEGV, &act, NULL); | ||
189 | |||
190 | filesize = lseek(fd, 0, SEEK_END); | ||
191 | if (filesize & 0xffff) | ||
192 | filesize &= ~0xfffful; | ||
193 | |||
194 | fileblock = mmap(NULL, filesize, PROT_READ | PROT_WRITE, | ||
195 | MAP_SHARED, fd, 0); | ||
196 | if (fileblock == MAP_FAILED) { | ||
197 | perror("failed to map file"); | ||
198 | return 1; | ||
199 | } | ||
200 | printf("allocated %s for 0x%lx bytes at 0x%p\n", | ||
201 | file_name, filesize, fileblock); | ||
202 | |||
203 | printf("testing file map...\n"); | ||
204 | |||
205 | return run_test(fileblock, filesize); | ||
206 | } | ||
207 | |||
208 | int main(int argc, char *argv[]) | ||
209 | { | ||
210 | test_harness(test_anon, "subpage_prot_anon"); | ||
211 | |||
212 | if (argc > 1) | ||
213 | file_name = argv[1]; | ||
214 | else | ||
215 | file_name = "tempfile"; | ||
216 | |||
217 | test_harness(test_file, "subpage_prot_file"); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/.gitignore b/tools/testing/selftests/powerpc/pmu/.gitignore new file mode 100644 index 000000000000..e748f336eed3 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | count_instructions | ||
2 | l3_bank_test | ||
3 | per_event_excludes | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore new file mode 100644 index 000000000000..42bddbed8b64 --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore | |||
@@ -0,0 +1,22 @@ | |||
1 | reg_access_test | ||
2 | event_attributes_test | ||
3 | cycles_test | ||
4 | cycles_with_freeze_test | ||
5 | pmc56_overflow_test | ||
6 | ebb_vs_cpu_event_test | ||
7 | cpu_event_vs_ebb_test | ||
8 | cpu_event_pinned_vs_ebb_test | ||
9 | task_event_vs_ebb_test | ||
10 | task_event_pinned_vs_ebb_test | ||
11 | multi_ebb_procs_test | ||
12 | multi_counter_test | ||
13 | pmae_handling_test | ||
14 | close_clears_pmcc_test | ||
15 | instruction_count_test | ||
16 | fork_cleanup_test | ||
17 | ebb_on_child_test | ||
18 | ebb_on_willing_child_test | ||
19 | back_to_back_ebbs_test | ||
20 | lost_exception_test | ||
21 | no_handler_test | ||
22 | cycles_with_mmcr2_test | ||
diff --git a/tools/testing/selftests/powerpc/primitives/.gitignore b/tools/testing/selftests/powerpc/primitives/.gitignore new file mode 100644 index 000000000000..4cc4e31bed1d --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/.gitignore | |||
@@ -0,0 +1 @@ | |||
load_unaligned_zeropad | |||
diff --git a/tools/testing/selftests/powerpc/stringloops/.gitignore b/tools/testing/selftests/powerpc/stringloops/.gitignore new file mode 100644 index 000000000000..0b43da74ee46 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/.gitignore | |||
@@ -0,0 +1 @@ | |||
memcmp | |||
diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile new file mode 100644 index 000000000000..506d77346477 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/Makefile | |||
@@ -0,0 +1,20 @@ | |||
1 | # The loops are all 64-bit code | ||
2 | CFLAGS += -m64 | ||
3 | CFLAGS += -I$(CURDIR) | ||
4 | |||
5 | PROGS := memcmp | ||
6 | EXTRA_SOURCES := memcmp_64.S ../harness.c | ||
7 | |||
8 | all: $(PROGS) | ||
9 | |||
10 | $(PROGS): $(EXTRA_SOURCES) | ||
11 | |||
12 | run_tests: all | ||
13 | @-for PROG in $(PROGS); do \ | ||
14 | ./$$PROG; \ | ||
15 | done; | ||
16 | |||
17 | clean: | ||
18 | rm -f $(PROGS) *.o | ||
19 | |||
20 | .PHONY: all run_tests clean | ||
diff --git a/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h new file mode 100644 index 000000000000..11bece87e880 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #include <ppc-asm.h> | ||
2 | |||
3 | #ifndef r1 | ||
4 | #define r1 sp | ||
5 | #endif | ||
6 | |||
7 | #define _GLOBAL(A) FUNC_START(test_ ## A) | ||
diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp.c b/tools/testing/selftests/powerpc/stringloops/memcmp.c new file mode 100644 index 000000000000..17417dd70708 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/memcmp.c | |||
@@ -0,0 +1,103 @@ | |||
1 | #include <malloc.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "../utils.h" | ||
5 | |||
6 | #define SIZE 256 | ||
7 | #define ITERATIONS 10000 | ||
8 | |||
9 | int test_memcmp(const void *s1, const void *s2, size_t n); | ||
10 | |||
11 | /* test all offsets and lengths */ | ||
12 | static void test_one(char *s1, char *s2) | ||
13 | { | ||
14 | unsigned long offset, size; | ||
15 | |||
16 | for (offset = 0; offset < SIZE; offset++) { | ||
17 | for (size = 0; size < (SIZE-offset); size++) { | ||
18 | int x, y; | ||
19 | unsigned long i; | ||
20 | |||
21 | y = memcmp(s1+offset, s2+offset, size); | ||
22 | x = test_memcmp(s1+offset, s2+offset, size); | ||
23 | |||
24 | if (((x ^ y) < 0) && /* Trick to compare sign */ | ||
25 | ((x | y) != 0)) { /* check for zero */ | ||
26 | printf("memcmp returned %d, should have returned %d (offset %ld size %ld)\n", x, y, offset, size); | ||
27 | |||
28 | for (i = offset; i < offset+size; i++) | ||
29 | printf("%02x ", s1[i]); | ||
30 | printf("\n"); | ||
31 | |||
32 | for (i = offset; i < offset+size; i++) | ||
33 | printf("%02x ", s2[i]); | ||
34 | printf("\n"); | ||
35 | abort(); | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static int testcase(void) | ||
42 | { | ||
43 | char *s1; | ||
44 | char *s2; | ||
45 | unsigned long i; | ||
46 | |||
47 | s1 = memalign(128, SIZE); | ||
48 | if (!s1) { | ||
49 | perror("memalign"); | ||
50 | exit(1); | ||
51 | } | ||
52 | |||
53 | s2 = memalign(128, SIZE); | ||
54 | if (!s2) { | ||
55 | perror("memalign"); | ||
56 | exit(1); | ||
57 | } | ||
58 | |||
59 | srandom(1); | ||
60 | |||
61 | for (i = 0; i < ITERATIONS; i++) { | ||
62 | unsigned long j; | ||
63 | unsigned long change; | ||
64 | |||
65 | for (j = 0; j < SIZE; j++) | ||
66 | s1[j] = random(); | ||
67 | |||
68 | memcpy(s2, s1, SIZE); | ||
69 | |||
70 | /* change one byte */ | ||
71 | change = random() % SIZE; | ||
72 | s2[change] = random() & 0xff; | ||
73 | |||
74 | test_one(s1, s2); | ||
75 | } | ||
76 | |||
77 | srandom(1); | ||
78 | |||
79 | for (i = 0; i < ITERATIONS; i++) { | ||
80 | unsigned long j; | ||
81 | unsigned long change; | ||
82 | |||
83 | for (j = 0; j < SIZE; j++) | ||
84 | s1[j] = random(); | ||
85 | |||
86 | memcpy(s2, s1, SIZE); | ||
87 | |||
88 | /* change multiple bytes, 1/8 of total */ | ||
89 | for (j = 0; j < SIZE / 8; j++) { | ||
90 | change = random() % SIZE; | ||
91 | s2[change] = random() & 0xff; | ||
92 | } | ||
93 | |||
94 | test_one(s1, s2); | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | int main(void) | ||
101 | { | ||
102 | return test_harness(testcase, "memcmp"); | ||
103 | } | ||
diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp_64.S b/tools/testing/selftests/powerpc/stringloops/memcmp_64.S new file mode 120000 index 000000000000..9bc87e438ae9 --- /dev/null +++ b/tools/testing/selftests/powerpc/stringloops/memcmp_64.S | |||
@@ -0,0 +1 @@ | |||
../../../../../arch/powerpc/lib/memcmp_64.S \ No newline at end of file | |||
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore new file mode 100644 index 000000000000..33d02cc54a3e --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/.gitignore | |||
@@ -0,0 +1 @@ | |||
tm-resched-dscr | |||