aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/testing/ktest/ktest.pl259
-rw-r--r--tools/testing/selftests/powerpc/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/copyloops/.gitignore4
-rw-r--r--tools/testing/selftests/powerpc/mm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile9
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c220
-rw-r--r--tools/testing/selftests/powerpc/pmu/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/.gitignore22
-rw-r--r--tools/testing/selftests/powerpc/primitives/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/stringloops/Makefile20
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/ppc_asm.h7
-rw-r--r--tools/testing/selftests/powerpc/stringloops/memcmp.c103
l---------tools/testing/selftests/powerpc/stringloops/memcmp_64.S1
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore1
-rw-r--r--tools/vm/page-types.c1
16 files changed, 623 insertions, 34 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index b9cd036f0442..d08e214ec6e7 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -178,6 +178,7 @@ my $checkout;
my $localversion;
my $iteration = 0;
my $successes = 0;
+my $stty_orig;
my $bisect_good;
my $bisect_bad;
@@ -197,6 +198,11 @@ my $patchcheck_start;
my $patchcheck_cherry;
my $patchcheck_end;
+my $build_time;
+my $install_time;
+my $reboot_time;
+my $test_time;
+
# set when a test is something other that just building or install
# which would require more options.
my $buildonly = 1;
@@ -554,6 +560,66 @@ sub get_mandatory_config {
}
}
+sub show_time {
+ my ($time) = @_;
+
+ my $hours = 0;
+ my $minutes = 0;
+
+ if ($time > 3600) {
+ $hours = int($time / 3600);
+ $time -= $hours * 3600;
+ }
+ if ($time > 60) {
+ $minutes = int($time / 60);
+ $time -= $minutes * 60;
+ }
+
+ if ($hours > 0) {
+ doprint "$hours hour";
+ doprint "s" if ($hours > 1);
+ doprint " ";
+ }
+
+ if ($minutes > 0) {
+ doprint "$minutes minute";
+ doprint "s" if ($minutes > 1);
+ doprint " ";
+ }
+
+ doprint "$time second";
+ doprint "s" if ($time != 1);
+}
+
+sub print_times {
+ doprint "\n";
+ if ($build_time) {
+ doprint "Build time: ";
+ show_time($build_time);
+ doprint "\n";
+ }
+ if ($install_time) {
+ doprint "Install time: ";
+ show_time($install_time);
+ doprint "\n";
+ }
+ if ($reboot_time) {
+ doprint "Reboot time: ";
+ show_time($reboot_time);
+ doprint "\n";
+ }
+ if ($test_time) {
+ doprint "Test time: ";
+ show_time($test_time);
+ doprint "\n";
+ }
+ # reset for iterations like bisect
+ $build_time = 0;
+ $install_time = 0;
+ $reboot_time = 0;
+ $test_time = 0;
+}
+
sub get_mandatory_configs {
get_mandatory_config("MACHINE");
get_mandatory_config("BUILD_DIR");
@@ -1341,23 +1407,83 @@ sub dodie {
print " See $opt{LOG_FILE} for more info.\n";
}
+ if ($monitor_cnt) {
+ # restore terminal settings
+ system("stty $stty_orig");
+ }
+
die @_, "\n";
}
+sub create_pty {
+ my ($ptm, $pts) = @_;
+ my $tmp;
+ my $TIOCSPTLCK = 0x40045431;
+ my $TIOCGPTN = 0x80045430;
+
+ sysopen($ptm, "/dev/ptmx", O_RDWR | O_NONBLOCK) or
+ dodie "Cant open /dev/ptmx";
+
+ # unlockpt()
+ $tmp = pack("i", 0);
+ ioctl($ptm, $TIOCSPTLCK, $tmp) or
+ dodie "ioctl TIOCSPTLCK for /dev/ptmx failed";
+
+ # ptsname()
+ ioctl($ptm, $TIOCGPTN, $tmp) or
+ dodie "ioctl TIOCGPTN for /dev/ptmx failed";
+ $tmp = unpack("i", $tmp);
+
+ sysopen($pts, "/dev/pts/$tmp", O_RDWR | O_NONBLOCK) or
+ dodie "Can't open /dev/pts/$tmp";
+}
+
+sub exec_console {
+ my ($ptm, $pts) = @_;
+
+ close($ptm);
+
+ close(\*STDIN);
+ close(\*STDOUT);
+ close(\*STDERR);
+
+ open(\*STDIN, '<&', $pts);
+ open(\*STDOUT, '>&', $pts);
+ open(\*STDERR, '>&', $pts);
+
+ close($pts);
+
+ exec $console or
+ die "Can't open console $console";
+}
+
sub open_console {
- my ($fp) = @_;
+ my ($ptm) = @_;
+ my $pts = \*PTSFD;
+ my $pid;
- my $flags;
+ # save terminal settings
+ $stty_orig = `stty -g`;
- my $pid = open($fp, "$console|") or
- dodie "Can't open console $console";
+ # place terminal in cbreak mode so that stdin can be read one character at
+ # a time without having to wait for a newline
+ system("stty -icanon -echo -icrnl");
- $flags = fcntl($fp, F_GETFL, 0) or
- dodie "Can't get flags for the socket: $!";
- $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
- dodie "Can't set flags for the socket: $!";
+ create_pty($ptm, $pts);
+
+ $pid = fork;
+
+ if (!$pid) {
+ # child
+ exec_console($ptm, $pts)
+ }
+
+ # parent
+ close($pts);
return $pid;
+
+ open(PTSFD, "Stop perl from warning about single use of PTSFD");
}
sub close_console {
@@ -1368,6 +1494,9 @@ sub close_console {
print "closing!\n";
close($fp);
+
+ # restore terminal settings
+ system("stty $stty_orig");
}
sub start_monitor {
@@ -1519,6 +1648,8 @@ sub fail {
$name = " ($test_name)";
}
+ print_times;
+
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
@@ -1534,10 +1665,14 @@ sub fail {
sub run_command {
my ($command, $redirect) = @_;
+ my $start_time;
+ my $end_time;
my $dolog = 0;
my $dord = 0;
my $pid;
+ $start_time = time;
+
$command =~ s/\$SSH_USER/$ssh_user/g;
$command =~ s/\$MACHINE/$machine/g;
@@ -1570,6 +1705,15 @@ sub run_command {
close(LOG) if ($dolog);
close(RD) if ($dord);
+ $end_time = time;
+ my $delta = $end_time - $start_time;
+
+ if ($delta == 1) {
+ doprint "[1 second] ";
+ } else {
+ doprint "[$delta seconds] ";
+ }
+
if ($failed) {
doprint "FAILED!\n";
} else {
@@ -1694,7 +1838,9 @@ sub wait_for_input
{
my ($fp, $time) = @_;
my $rin;
- my $ready;
+ my $rout;
+ my $nr;
+ my $buf;
my $line;
my $ch;
@@ -1704,21 +1850,36 @@ sub wait_for_input
$rin = '';
vec($rin, fileno($fp), 1) = 1;
- ($ready, $time) = select($rin, undef, undef, $time);
+ vec($rin, fileno(\*STDIN), 1) = 1;
- $line = "";
+ while (1) {
+ $nr = select($rout=$rin, undef, undef, $time);
- # try to read one char at a time
- while (sysread $fp, $ch, 1) {
- $line .= $ch;
- last if ($ch eq "\n");
- }
+ if ($nr <= 0) {
+ return undef;
+ }
- if (!length($line)) {
- return undef;
- }
+ # copy data from stdin to the console
+ if (vec($rout, fileno(\*STDIN), 1) == 1) {
+ sysread(\*STDIN, $buf, 1000);
+ syswrite($fp, $buf, 1000);
+ next;
+ }
- return $line;
+ $line = "";
+
+ # try to read one char at a time
+ while (sysread $fp, $ch, 1) {
+ $line .= $ch;
+ last if ($ch eq "\n");
+ }
+
+ if (!length($line)) {
+ return undef;
+ }
+
+ return $line;
+ }
}
sub reboot_to {
@@ -1766,6 +1927,8 @@ sub monitor {
my $skip_call_trace = 0;
my $loops;
+ my $start_time = time;
+
wait_for_monitor 5;
my $line;
@@ -1890,6 +2053,9 @@ sub monitor {
}
}
+ my $end_time = time;
+ $reboot_time = $end_time - $start_time;
+
close(DMESG);
if ($bug) {
@@ -1938,6 +2104,8 @@ sub install {
return if ($no_install);
+ my $start_time = time;
+
if (defined($pre_install)) {
my $cp_pre_install = eval_kernel_version $pre_install;
run_command "$cp_pre_install" or
@@ -1969,6 +2137,8 @@ sub install {
if (!$install_mods) {
do_post_install;
doprint "No modules needed\n";
+ my $end_time = time;
+ $install_time = $end_time - $start_time;
return;
}
@@ -1996,6 +2166,9 @@ sub install {
run_ssh "rm -f /tmp/$modtar";
do_post_install;
+
+ my $end_time = time;
+ $install_time = $end_time - $start_time;
}
sub get_version {
@@ -2008,7 +2181,7 @@ sub get_version {
$have_version = 1;
}
-sub start_monitor_and_boot {
+sub start_monitor_and_install {
# Make sure the stable kernel has finished booting
# Install bisects, don't need console
@@ -2208,6 +2381,8 @@ sub build {
unlink $buildlog;
+ my $start_time = time;
+
# Failed builds should not reboot the target
my $save_no_reboot = $no_reboot;
$no_reboot = 1;
@@ -2293,6 +2468,9 @@ sub build {
$no_reboot = $save_no_reboot;
+ my $end_time = time;
+ $build_time = $end_time - $start_time;
+
return 1;
}
@@ -2323,6 +2501,8 @@ sub success {
$name = " ($test_name)";
}
+ print_times;
+
doprint "\n\n*******************************************\n";
doprint "*******************************************\n";
doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
@@ -2383,6 +2563,8 @@ sub do_run_test {
my $bug = 0;
my $bug_ignored = 0;
+ my $start_time = time;
+
wait_for_monitor 1;
doprint "run test $run_test\n";
@@ -2449,6 +2631,9 @@ sub do_run_test {
waitpid $child_pid, 0;
$child_exit = $?;
+ my $end_time = time;
+ $test_time = $end_time - $start_time;
+
if (!$bug && $in_bisect) {
if (defined($bisect_ret_good)) {
if ($child_exit == $bisect_ret_good) {
@@ -2549,7 +2734,7 @@ sub run_bisect_test {
dodie "Failed on build" if $failed;
# Now boot the box
- start_monitor_and_boot or $failed = 1;
+ start_monitor_and_install or $failed = 1;
if ($type ne "boot") {
if ($failed && $bisect_skip) {
@@ -2755,6 +2940,7 @@ sub bisect {
do {
$result = run_bisect $type;
$test = run_git_bisect "git bisect $result";
+ print_times;
} while ($test);
run_command "git bisect log" or
@@ -3168,6 +3354,7 @@ sub config_bisect {
do {
$ret = run_config_bisect \%good_configs, \%bad_configs;
+ print_times;
} while (!$ret);
return $ret if ($ret < 0);
@@ -3260,7 +3447,7 @@ sub patchcheck {
my $sha1 = $item;
$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
- doprint "\nProcessing commit $item\n\n";
+ doprint "\nProcessing commit \"$item\"\n\n";
run_command "git checkout $sha1" or
die "Failed to checkout $sha1";
@@ -3291,16 +3478,18 @@ sub patchcheck {
my $failed = 0;
- start_monitor_and_boot or $failed = 1;
+ start_monitor_and_install or $failed = 1;
if (!$failed && $type ne "boot"){
do_run_test or $failed = 1;
}
end_monitor;
- return 0 if ($failed);
-
+ if ($failed) {
+ print_times;
+ return 0;
+ }
patchcheck_reboot;
-
+ print_times;
}
$in_patchcheck = 0;
success $i;
@@ -3753,7 +3942,7 @@ sub make_min_config {
my $failed = 0;
build "oldconfig" or $failed = 1;
if (!$failed) {
- start_monitor_and_boot or $failed = 1;
+ start_monitor_and_install or $failed = 1;
if ($type eq "test" && !$failed) {
do_run_test or $failed = 1;
@@ -4000,6 +4189,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
$iteration = $i;
+ $build_time = 0;
+ $install_time = 0;
+ $reboot_time = 0;
+ $test_time = 0;
+
undef %force_config;
my $makecmd = set_test_option("MAKE_CMD", $i);
@@ -4157,15 +4351,20 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
if ($test_type ne "build") {
my $failed = 0;
- start_monitor_and_boot or $failed = 1;
+ start_monitor_and_install or $failed = 1;
if (!$failed && $test_type ne "boot" && defined($run_test)) {
do_run_test or $failed = 1;
}
end_monitor;
- next if ($failed);
+ if ($failed) {
+ print_times;
+ next;
+ }
}
+ print_times;
+
success $i;
}
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
export CC CFLAGS
-TARGETS = pmu copyloops mm tm primitives
+TARGETS = pmu copyloops mm tm primitives stringloops
endif
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 @@
+copyuser_64
+copyuser_power7
+memcpy_64
+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 @@
+hugetlb_vs_thp_test
+subpage_prot
+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 @@
noarg:
$(MAKE) -C ../
-PROGS := hugetlb_vs_thp_test
+PROGS := hugetlb_vs_thp_test subpage_prot
-all: $(PROGS)
+all: $(PROGS) tempfile
$(PROGS): ../harness.c
@@ -12,7 +12,10 @@ run_tests: all
./$$PROG; \
done;
+tempfile:
+ dd if=/dev/zero of=tempfile bs=64k count=1
+
clean:
- rm -f $(PROGS)
+ rm -f $(PROGS) tempfile
.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 @@
+/*
+ * Copyright IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+char *file_name;
+
+int in_test;
+volatile int faulted;
+volatile void *dar;
+int errors;
+
+static void segv(int signum, siginfo_t *info, void *ctxt_v)
+{
+ ucontext_t *ctxt = (ucontext_t *)ctxt_v;
+ struct pt_regs *regs = ctxt->uc_mcontext.regs;
+
+ if (!in_test) {
+ fprintf(stderr, "Segfault outside of test !\n");
+ exit(1);
+ }
+
+ faulted = 1;
+ dar = (void *)regs->dar;
+ regs->nip += 4;
+}
+
+static inline void do_read(const volatile void *addr)
+{
+ int ret;
+
+ asm volatile("lwz %0,0(%1); twi 0,%0,0; isync;\n"
+ : "=r" (ret) : "r" (addr) : "memory");
+}
+
+static inline void do_write(const volatile void *addr)
+{
+ int val = 0x1234567;
+
+ asm volatile("stw %0,0(%1); sync; \n"
+ : : "r" (val), "r" (addr) : "memory");
+}
+
+static inline void check_faulted(void *addr, long page, long subpage, int write)
+{
+ int want_fault = (subpage == ((page + 3) % 16));
+
+ if (write)
+ want_fault |= (subpage == ((page + 1) % 16));
+
+ if (faulted != want_fault) {
+ printf("Failed at 0x%p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n",
+ addr, page, subpage, write,
+ want_fault ? "fault" : "pass",
+ faulted ? "fault" : "pass");
+ ++errors;
+ }
+
+ if (faulted) {
+ if (dar != addr) {
+ printf("Fault expected at 0x%p and happened at 0x%p !\n",
+ addr, dar);
+ }
+ faulted = 0;
+ asm volatile("sync" : : : "memory");
+ }
+}
+
+static int run_test(void *addr, unsigned long size)
+{
+ unsigned int *map;
+ long i, j, pages, err;
+
+ pages = size / 0x10000;
+ map = malloc(pages * 4);
+ assert(map);
+
+ /*
+ * for each page, mark subpage i % 16 read only and subpage
+ * (i + 3) % 16 inaccessible
+ */
+ for (i = 0; i < pages; i++) {
+ map[i] = (0x40000000 >> (((i + 1) * 2) % 32)) |
+ (0xc0000000 >> (((i + 3) * 2) % 32));
+ }
+
+ err = syscall(__NR_subpage_prot, addr, size, map);
+ if (err) {
+ perror("subpage_perm");
+ return 1;
+ }
+ free(map);
+
+ in_test = 1;
+ errors = 0;
+ for (i = 0; i < pages; i++) {
+ for (j = 0; j < 16; j++, addr += 0x1000) {
+ do_read(addr);
+ check_faulted(addr, i, j, 0);
+ do_write(addr);
+ check_faulted(addr, i, j, 1);
+ }
+ }
+
+ in_test = 0;
+ if (errors) {
+ printf("%d errors detected\n", errors);
+ return 1;
+ }
+
+ return 0;
+}
+
+int test_anon(void)
+{
+ unsigned long align;
+ struct sigaction act = {
+ .sa_sigaction = segv,
+ .sa_flags = SA_SIGINFO
+ };
+ void *mallocblock;
+ unsigned long mallocsize;
+
+ if (getpagesize() != 0x10000) {
+ fprintf(stderr, "Kernel page size must be 64K!\n");
+ return 1;
+ }
+
+ sigaction(SIGSEGV, &act, NULL);
+
+ mallocsize = 4 * 16 * 1024 * 1024;
+
+ FAIL_IF(posix_memalign(&mallocblock, 64 * 1024, mallocsize));
+
+ align = (unsigned long)mallocblock;
+ if (align & 0xffff)
+ align = (align | 0xffff) + 1;
+
+ mallocblock = (void *)align;
+
+ printf("allocated malloc block of 0x%lx bytes at 0x%p\n",
+ mallocsize, mallocblock);
+
+ printf("testing malloc block...\n");
+
+ return run_test(mallocblock, mallocsize);
+}
+
+int test_file(void)
+{
+ struct sigaction act = {
+ .sa_sigaction = segv,
+ .sa_flags = SA_SIGINFO
+ };
+ void *fileblock;
+ off_t filesize;
+ int fd;
+
+ fd = open(file_name, O_RDWR);
+ if (fd == -1) {
+ perror("failed to open file");
+ return 1;
+ }
+ sigaction(SIGSEGV, &act, NULL);
+
+ filesize = lseek(fd, 0, SEEK_END);
+ if (filesize & 0xffff)
+ filesize &= ~0xfffful;
+
+ fileblock = mmap(NULL, filesize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (fileblock == MAP_FAILED) {
+ perror("failed to map file");
+ return 1;
+ }
+ printf("allocated %s for 0x%lx bytes at 0x%p\n",
+ file_name, filesize, fileblock);
+
+ printf("testing file map...\n");
+
+ return run_test(fileblock, filesize);
+}
+
+int main(int argc, char *argv[])
+{
+ test_harness(test_anon, "subpage_prot_anon");
+
+ if (argc > 1)
+ file_name = argv[1];
+ else
+ file_name = "tempfile";
+
+ test_harness(test_file, "subpage_prot_file");
+
+ return 0;
+}
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 @@
+count_instructions
+l3_bank_test
+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 @@
+reg_access_test
+event_attributes_test
+cycles_test
+cycles_with_freeze_test
+pmc56_overflow_test
+ebb_vs_cpu_event_test
+cpu_event_vs_ebb_test
+cpu_event_pinned_vs_ebb_test
+task_event_vs_ebb_test
+task_event_pinned_vs_ebb_test
+multi_ebb_procs_test
+multi_counter_test
+pmae_handling_test
+close_clears_pmcc_test
+instruction_count_test
+fork_cleanup_test
+ebb_on_child_test
+ebb_on_willing_child_test
+back_to_back_ebbs_test
+lost_exception_test
+no_handler_test
+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 @@
+# The loops are all 64-bit code
+CFLAGS += -m64
+CFLAGS += -I$(CURDIR)
+
+PROGS := memcmp
+EXTRA_SOURCES := memcmp_64.S ../harness.c
+
+all: $(PROGS)
+
+$(PROGS): $(EXTRA_SOURCES)
+
+run_tests: all
+ @-for PROG in $(PROGS); do \
+ ./$$PROG; \
+ done;
+
+clean:
+ rm -f $(PROGS) *.o
+
+.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 @@
+#include <ppc-asm.h>
+
+#ifndef r1
+#define r1 sp
+#endif
+
+#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 @@
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../utils.h"
+
+#define SIZE 256
+#define ITERATIONS 10000
+
+int test_memcmp(const void *s1, const void *s2, size_t n);
+
+/* test all offsets and lengths */
+static void test_one(char *s1, char *s2)
+{
+ unsigned long offset, size;
+
+ for (offset = 0; offset < SIZE; offset++) {
+ for (size = 0; size < (SIZE-offset); size++) {
+ int x, y;
+ unsigned long i;
+
+ y = memcmp(s1+offset, s2+offset, size);
+ x = test_memcmp(s1+offset, s2+offset, size);
+
+ if (((x ^ y) < 0) && /* Trick to compare sign */
+ ((x | y) != 0)) { /* check for zero */
+ printf("memcmp returned %d, should have returned %d (offset %ld size %ld)\n", x, y, offset, size);
+
+ for (i = offset; i < offset+size; i++)
+ printf("%02x ", s1[i]);
+ printf("\n");
+
+ for (i = offset; i < offset+size; i++)
+ printf("%02x ", s2[i]);
+ printf("\n");
+ abort();
+ }
+ }
+ }
+}
+
+static int testcase(void)
+{
+ char *s1;
+ char *s2;
+ unsigned long i;
+
+ s1 = memalign(128, SIZE);
+ if (!s1) {
+ perror("memalign");
+ exit(1);
+ }
+
+ s2 = memalign(128, SIZE);
+ if (!s2) {
+ perror("memalign");
+ exit(1);
+ }
+
+ srandom(1);
+
+ for (i = 0; i < ITERATIONS; i++) {
+ unsigned long j;
+ unsigned long change;
+
+ for (j = 0; j < SIZE; j++)
+ s1[j] = random();
+
+ memcpy(s2, s1, SIZE);
+
+ /* change one byte */
+ change = random() % SIZE;
+ s2[change] = random() & 0xff;
+
+ test_one(s1, s2);
+ }
+
+ srandom(1);
+
+ for (i = 0; i < ITERATIONS; i++) {
+ unsigned long j;
+ unsigned long change;
+
+ for (j = 0; j < SIZE; j++)
+ s1[j] = random();
+
+ memcpy(s2, s1, SIZE);
+
+ /* change multiple bytes, 1/8 of total */
+ for (j = 0; j < SIZE / 8; j++) {
+ change = random() % SIZE;
+ s2[change] = random() & 0xff;
+ }
+
+ test_one(s1, s2);
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ return test_harness(testcase, "memcmp");
+}
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
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index 264fbc297e0b..8bdf16b8ba60 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -133,6 +133,7 @@ static const char * const page_flag_names[] = {
[KPF_KSM] = "x:ksm",
[KPF_THP] = "t:thp",
[KPF_BALLOON] = "o:balloon",
+ [KPF_ZERO_PAGE] = "z:zero_page",
[KPF_RESERVED] = "r:reserved",
[KPF_MLOCKED] = "m:mlocked",