From d8db9bc55a316d97d0acdf6ccc9f43b370acd358 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 27 Sep 2016 22:10:16 +0800 Subject: selftests/powerpc: Add Anton's null_syscall benchmark to the selftests Pull in a version of Anton's null_syscall benchmark: http://ozlabs.org/~anton/junkcode/null_syscall.c Suggested-by: Michael Ellerman Signed-off-by: Anton Blanchard Signed-off-by: Rui Teng Signed-off-by: Michael Ellerman --- .../selftests/powerpc/benchmarks/.gitignore | 3 +- .../testing/selftests/powerpc/benchmarks/Makefile | 2 +- .../selftests/powerpc/benchmarks/null_syscall.c | 157 +++++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/powerpc/benchmarks/null_syscall.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore index bce49eb..04dc1e6 100644 --- a/tools/testing/selftests/powerpc/benchmarks/.gitignore +++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore @@ -1,4 +1,5 @@ gettimeofday context_switch mmap_bench -futex_bench \ No newline at end of file +futex_bench +null_syscall diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile index a9adfb7..545077f 100644 --- a/tools/testing/selftests/powerpc/benchmarks/Makefile +++ b/tools/testing/selftests/powerpc/benchmarks/Makefile @@ -1,4 +1,4 @@ -TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench +TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench null_syscall CFLAGS += -O2 diff --git a/tools/testing/selftests/powerpc/benchmarks/null_syscall.c b/tools/testing/selftests/powerpc/benchmarks/null_syscall.c new file mode 100644 index 0000000..ecc14d6 --- /dev/null +++ b/tools/testing/selftests/powerpc/benchmarks/null_syscall.c @@ -0,0 +1,157 @@ +/* + * Test null syscall performance + * + * Copyright (C) 2009-2015 Anton Blanchard, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define NR_LOOPS 10000000 + +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile int soak_done; +unsigned long long clock_frequency; +unsigned long long timebase_frequency; +double timebase_multiplier; + +static inline unsigned long long mftb(void) +{ + unsigned long low; + + asm volatile("mftb %0" : "=r" (low)); + + return low; +} + +static void sigalrm_handler(int unused) +{ + soak_done = 1; +} + +/* + * Use a timer instead of busy looping on clock_gettime() so we don't + * pollute profiles with glibc and VDSO hits. + */ +static void cpu_soak_usecs(unsigned long usecs) +{ + struct itimerval val; + + memset(&val, 0, sizeof(val)); + val.it_value.tv_usec = usecs; + + signal(SIGALRM, sigalrm_handler); + setitimer(ITIMER_REAL, &val, NULL); + + while (1) { + if (soak_done) + break; + } + + signal(SIGALRM, SIG_DFL); +} + +/* + * This only works with recent kernels where cpufreq modifies + * /proc/cpuinfo dynamically. + */ +static void get_proc_frequency(void) +{ + FILE *f; + char line[128]; + char *p, *end; + unsigned long v; + double d; + char *override; + + /* Try to get out of low power/low frequency mode */ + cpu_soak_usecs(0.25 * 1000000); + + f = fopen("/proc/cpuinfo", "r"); + if (f == NULL) + return; + + timebase_frequency = 0; + + while (fgets(line, sizeof(line), f) != NULL) { + if (strncmp(line, "timebase", 8) == 0) { + p = strchr(line, ':'); + if (p != NULL) { + v = strtoull(p + 1, &end, 0); + if (end != p + 1) + timebase_frequency = v; + } + } + + if (((strncmp(line, "clock", 5) == 0) || + (strncmp(line, "cpu MHz", 7) == 0))) { + p = strchr(line, ':'); + if (p != NULL) { + d = strtod(p + 1, &end); + if (end != p + 1) { + /* Find fastest clock frequency */ + if ((d * 1000000ULL) > clock_frequency) + clock_frequency = d * 1000000ULL; + } + } + } + } + + fclose(f); + + override = getenv("FREQUENCY"); + if (override) + clock_frequency = strtoull(override, NULL, 10); + + if (timebase_frequency) + timebase_multiplier = (double)clock_frequency + / timebase_frequency; + else + timebase_multiplier = 1; +} + +static void do_null_syscall(unsigned long nr) +{ + unsigned long i; + + for (i = 0; i < nr; i++) + getppid(); +} + +#define TIME(A, STR) \ + +int main(void) +{ + unsigned long tb_start, tb_now; + struct timespec tv_start, tv_now; + unsigned long long elapsed_ns, elapsed_tb; + + get_proc_frequency(); + + clock_gettime(CLOCK_MONOTONIC, &tv_start); + tb_start = mftb(); + + do_null_syscall(NR_LOOPS); + + clock_gettime(CLOCK_MONOTONIC, &tv_now); + tb_now = mftb(); + + elapsed_ns = (tv_now.tv_sec - tv_start.tv_sec) * 1000000000ULL + + (tv_now.tv_nsec - tv_start.tv_nsec); + elapsed_tb = tb_now - tb_start; + + printf("%10.2f ns %10.2f cycles\n", (float)elapsed_ns / NR_LOOPS, + (float)elapsed_tb * timebase_multiplier / NR_LOOPS); + + return 0; +} -- cgit v1.1 From 06236f4efb926aa433e2cb3e36e8467f4a0e42c0 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 1 Nov 2016 15:01:07 +1100 Subject: selftests/powerpc: Abort load_unaligned_zeropad on unhandled SEGV If the load unaligned zeropad test takes a SEGV which can't be handled, we increment segv_error, print the offending NIP and then return without taking any further action. In almost all cases this means we'll just take the SEGV again, and loop eternally spamming the console. Instead just abort(), it's a fatal error in the test. The test harness will notice that the child died and print a nice message for us. Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c index 6cae061..cf7a4a1 100644 --- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c +++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c @@ -73,7 +73,6 @@ extern char __stop___ex_table[]; #error implement UCONTEXT_NIA #endif -static int segv_error; static void segv_handler(int signr, siginfo_t *info, void *ptr) { @@ -95,7 +94,7 @@ static void segv_handler(int signr, siginfo_t *info, void *ptr) } printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr); - segv_error++; + abort(); } static void setup_segv_handler(void) @@ -145,8 +144,6 @@ static int test_body(void) for (i = 0; i < page_size; i++) FAIL_IF(do_one_test(mem_region+i, i)); - FAIL_IF(segv_error); - return 0; } -- cgit v1.1 From 997e200182347d2cc7e37bc43eaafe249b4571b9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 1 Nov 2016 15:01:18 +1100 Subject: selftests/powerpc: Fail load_unaligned_zeropad on miscompare If the result returned by load_unaligned_zeropad() doesn't match what we expect we should fail the test! Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c index cf7a4a1..cd7af4e 100644 --- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c +++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c @@ -118,8 +118,10 @@ static int do_one_test(char *p, int page_offset) got = load_unaligned_zeropad(p); - if (should != got) + if (should != got) { printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should); + return 1; + } return 0; } -- cgit v1.1 From 24bfa6a9e0d4fe414dfc4ad06c93e10c4c37194e Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 13 Oct 2016 16:42:53 +1100 Subject: powerpc: EX_TABLE macro for exception tables This macro is taken from s390, and allows more flexibility in changing exception table format. mpe: Put it in ppc_asm.h and only define one version using stringinfy_in_c(). Add some empty definitions and headers to keep the selftests happy. Signed-off-by: Nicholas Piggin Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h | 2 ++ tools/testing/selftests/powerpc/primitives/asm/firmware.h | 0 tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h | 1 + tools/testing/selftests/powerpc/primitives/asm/processor.h | 0 tools/testing/selftests/powerpc/primitives/linux/stringify.h | 0 5 files changed, 3 insertions(+) create mode 100644 tools/testing/selftests/powerpc/primitives/asm/firmware.h create mode 120000 tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h create mode 100644 tools/testing/selftests/powerpc/primitives/asm/processor.h create mode 100644 tools/testing/selftests/powerpc/primitives/linux/stringify.h (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h index 50ae7d2..80d34a9 100644 --- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h +++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h @@ -25,6 +25,8 @@ #define PPC_MTOCRF(A, B) mtocrf A, B +#define EX_TABLE(x, y) + FUNC_START(enter_vmx_usercopy) li r3,1 blr diff --git a/tools/testing/selftests/powerpc/primitives/asm/firmware.h b/tools/testing/selftests/powerpc/primitives/asm/firmware.h new file mode 100644 index 0000000..e69de29 diff --git a/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h b/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h new file mode 120000 index 0000000..66c81932 --- /dev/null +++ b/tools/testing/selftests/powerpc/primitives/asm/ppc_asm.h @@ -0,0 +1 @@ +../../../../../../arch/powerpc/include/asm/ppc_asm.h \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/primitives/asm/processor.h b/tools/testing/selftests/powerpc/primitives/asm/processor.h new file mode 100644 index 0000000..e69de29 diff --git a/tools/testing/selftests/powerpc/primitives/linux/stringify.h b/tools/testing/selftests/powerpc/primitives/linux/stringify.h new file mode 100644 index 0000000..e69de29 -- cgit v1.1 From 61a92f703120daf7ed25e046275aa8a2d3085ad4 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Fri, 14 Oct 2016 16:47:31 +1100 Subject: powerpc: Add support for relative exception tables This halves the exception table size on 64-bit builds, and it allows build-time sorting of exception tables to work on relocated kernels. Signed-off-by: Nicholas Piggin [mpe: Minor asm fixups and bits to keep the selftests working] Signed-off-by: Michael Ellerman --- .../selftests/powerpc/primitives/load_unaligned_zeropad.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c index cd7af4e..ed3239b 100644 --- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c +++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c @@ -73,19 +73,23 @@ extern char __stop___ex_table[]; #error implement UCONTEXT_NIA #endif +struct extbl_entry { + int insn; + int fixup; +}; static void segv_handler(int signr, siginfo_t *info, void *ptr) { ucontext_t *uc = (ucontext_t *)ptr; unsigned long addr = (unsigned long)info->si_addr; unsigned long *ip = &UCONTEXT_NIA(uc); - unsigned long *ex_p = (unsigned long *)__start___ex_table; + struct extbl_entry *entry = (struct extbl_entry *)__start___ex_table; - while (ex_p < (unsigned long *)__stop___ex_table) { + while (entry < (struct extbl_entry *)__stop___ex_table) { unsigned long insn, fixup; - insn = *ex_p++; - fixup = *ex_p++; + insn = (unsigned long)&entry->insn + entry->insn; + fixup = (unsigned long)&entry->fixup + entry->fixup; if (insn == *ip) { *ip = fixup; -- cgit v1.1 From 7c65856b7e0d12f2be2adae7a75a11659285f5b9 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Mon, 31 Oct 2016 13:19:38 +1100 Subject: selftests/powerpc: Revert Load Monitor Register Tests Load monitored won't be supported in POWER9, so PPC_FEATURE2_ARCH_3_00 (in HWCAP2) will no longer imply Load monitor support. These Load monitored tests are enabled by PPC_FEATURE2_ARCH_3_00 so they are now bogus and need to be removed. This reverts commit 16c19a2e9833 ("selftests/powerpc: Load Monitor Register Tests"). Signed-off-by: Michael Neuling Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/pmu/ebb/.gitignore | 2 - tools/testing/selftests/powerpc/pmu/ebb/Makefile | 2 +- tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c | 143 --------------------- tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h | 39 ------ .../selftests/powerpc/pmu/ebb/ebb_lmr_regs.c | 37 ------ tools/testing/selftests/powerpc/reg.h | 5 - 6 files changed, 1 insertion(+), 227 deletions(-) delete mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c delete mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h delete mode 100644 tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore index 44b7df1..42bddbe 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore +++ b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore @@ -20,5 +20,3 @@ back_to_back_ebbs_test lost_exception_test no_handler_test cycles_with_mmcr2_test -ebb_lmr -ebb_lmr_regs \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile index 6b0453e..8d2279c4 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile +++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile @@ -14,7 +14,7 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_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 ebb_lmr ebb_lmr_regs + cycles_with_mmcr2_test all: $(TEST_PROGS) diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c deleted file mode 100644 index c47ebd5..0000000 --- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2016, Jack Miller, IBM Corp. - * Licensed under GPLv2. - */ - -#include -#include - -#include "ebb.h" -#include "ebb_lmr.h" - -#define SIZE (32 * 1024 * 1024) /* 32M */ -#define LM_SIZE 0 /* Smallest encoding, 32M */ - -#define SECTIONS 64 /* 1 per bit in LMSER */ -#define SECTION_SIZE (SIZE / SECTIONS) -#define SECTION_LONGS (SECTION_SIZE / sizeof(long)) - -static unsigned long *test_mem; - -static int lmr_count = 0; - -void ebb_lmr_handler(void) -{ - lmr_count++; -} - -void ldmx_full_section(unsigned long *mem, int section) -{ - unsigned long *ptr; - int i; - - for (i = 0; i < SECTION_LONGS; i++) { - ptr = &mem[(SECTION_LONGS * section) + i]; - ldmx((unsigned long) &ptr); - ebb_lmr_reset(); - } -} - -unsigned long section_masks[] = { - 0x8000000000000000, - 0xFF00000000000000, - 0x0000000F70000000, - 0x8000000000000001, - 0xF0F0F0F0F0F0F0F0, - 0x0F0F0F0F0F0F0F0F, - 0x0 -}; - -int ebb_lmr_section_test(unsigned long *mem) -{ - unsigned long *mask = section_masks; - int i; - - for (; *mask; mask++) { - mtspr(SPRN_LMSER, *mask); - printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER)); - - for (i = 0; i < 64; i++) { - lmr_count = 0; - ldmx_full_section(mem, i); - if (*mask & (1UL << (63 - i))) - FAIL_IF(lmr_count != SECTION_LONGS); - else - FAIL_IF(lmr_count); - } - } - - return 0; -} - -int ebb_lmr(void) -{ - int i; - - SKIP_IF(!lmr_is_supported()); - - setup_ebb_handler(ebb_lmr_handler); - - ebb_global_enable(); - - FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0); - - mtspr(SPRN_LMSER, 0); - - FAIL_IF(mfspr(SPRN_LMSER) != 0); - - mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE)); - - FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE)); - - /* Read every single byte to ensure we get no false positives */ - for (i = 0; i < SECTIONS; i++) - ldmx_full_section(test_mem, i); - - FAIL_IF(lmr_count != 0); - - /* Turn on the first section */ - - mtspr(SPRN_LMSER, (1UL << 63)); - FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63)); - - /* Enable LM (BESCR) */ - - mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME); - FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME)); - - ldmx((unsigned long)&test_mem); - - FAIL_IF(lmr_count != 1); // exactly one exception - FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled - FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set - - printf("Simple LMR EBB OK\n"); - - /* This shouldn't cause an EBB since it's been disabled */ - ldmx((unsigned long)&test_mem); - FAIL_IF(lmr_count != 1); - - printf("LMR disable on EBB OK\n"); - - ebb_lmr_reset(); - - /* This should cause an EBB or reset is broken */ - ldmx((unsigned long)&test_mem); - FAIL_IF(lmr_count != 2); - - printf("LMR reset EBB OK\n"); - - ebb_lmr_reset(); - - return ebb_lmr_section_test(test_mem); -} - -int main(void) -{ - int ret = test_harness(ebb_lmr, "ebb_lmr"); - - if (test_mem) - free(test_mem); - - return ret; -} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h deleted file mode 100644 index ef50abd..0000000 --- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _SELFTESTS_POWERPC_PMU_EBB_LMR_H -#define _SELFTESTS_POWERPC_PMU_EBB_LMR_H - -#include "reg.h" - -#ifndef PPC_FEATURE2_ARCH_3_00 -#define PPC_FEATURE2_ARCH_3_00 0x00800000 -#endif - -#define lmr_is_supported() have_hwcap2(PPC_FEATURE2_ARCH_3_00) - -static inline void ebb_lmr_reset(void) -{ - unsigned long bescr = mfspr(SPRN_BESCR); - bescr &= ~(BESCR_LMEO); - bescr |= BESCR_LME; - mtspr(SPRN_BESCR, bescr); -} - -#define LDMX(t, a, b)\ - (0x7c00026a | \ - (((t) & 0x1f) << 21) | \ - (((a) & 0x1f) << 16) | \ - (((b) & 0x1f) << 11)) - -static inline unsigned long ldmx(unsigned long address) -{ - unsigned long ret; - - asm volatile ("mr 9, %1\r\n" - ".long " __stringify(LDMX(9, 0, 9)) "\r\n" - "mr %0, 9\r\n":"=r"(ret) - :"r"(address) - :"r9"); - - return ret; -} - -#endif diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c deleted file mode 100644 index aff4241..0000000 --- a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2016, Jack Miller, IBM Corp. - * Licensed under GPLv2. - */ - -#include -#include -#include - -#include "ebb.h" -#include "ebb_lmr.h" - -#define CHECKS 10000 - -int ebb_lmr_regs(void) -{ - int i; - - SKIP_IF(!lmr_is_supported()); - - ebb_global_enable(); - - for (i = 0; i < CHECKS; i++) { - mtspr(SPRN_LMRR, i << 25); // skip size and rsvd bits - mtspr(SPRN_LMSER, i); - - FAIL_IF(mfspr(SPRN_LMRR) != (i << 25)); - FAIL_IF(mfspr(SPRN_LMSER) != i); - } - - return 0; -} - -int main(void) -{ - return test_harness(ebb_lmr_regs, "ebb_lmr_regs"); -} diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h index fddf368..65bfdee 100644 --- a/tools/testing/selftests/powerpc/reg.h +++ b/tools/testing/selftests/powerpc/reg.h @@ -34,11 +34,6 @@ #define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ #define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ -#define BESCR_LME (0x1ul << 34) /* Load Monitor Enable */ -#define BESCR_LMEO (0x1ul << 2) /* Load Monitor Exception Occurred */ - -#define SPRN_LMRR 813 /* Load Monitor Region Register */ -#define SPRN_LMSER 814 /* Load Monitor Section Enable Register */ #define SPRN_PMC1 771 #define SPRN_PMC2 772 -- cgit v1.1 From 0e27d27e0d6d92342797e0d37738c276c1ff090e Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 9 Nov 2016 09:55:04 +0100 Subject: selftests/powerpc: Return false instead of -1 in require_paranoia_below() Returning a negative value for a boolean function seem to have the undesired effect of returning true. require_paranoia_below() is a boolean function, but the variable used to store the return value is an integer, receiving -1 or 0. This patch converts rc to bool, replaces -1 by false, and 0 by true. mpe: This wasn't exhibiting in practice because the common case, where we do the comparison of the desired level vs the current value, was being compiled into a computation based on the result of the comparison, ie. it wasn't using the default -1 value at all. However that was just luck and the code is still wrong. Signed-off-by: Peter Senna Tschudin Signed-off-by: Andrew Shadura Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/pmu/lib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c index 8b992fa..5bf5dd4 100644 --- a/tools/testing/selftests/powerpc/pmu/lib.c +++ b/tools/testing/selftests/powerpc/pmu/lib.c @@ -193,9 +193,9 @@ bool require_paranoia_below(int level) long current; char *end, buf[16]; FILE *f; - int rc; + bool rc; - rc = -1; + rc = false; f = fopen(PARANOID_PATH, "r"); if (!f) { @@ -218,7 +218,7 @@ bool require_paranoia_below(int level) if (current >= level) goto out_close; - rc = 0; + rc = true; out_close: fclose(f); out: -- cgit v1.1 From efe71a67b5aa89e0348ac862ca92a57d98d3fd8d Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:50 +0800 Subject: selftests/powerpc: Add more SPR numbers, TM & VMX instructions to 'reg.h'/'instructions.h' This patch adds SPR number for TAR, PPR, DSCR special purpose registers. It also adds TM, VSX, VMX related instructions which will then be used by patches later in the series. Now that the new DSCR register definitions (SPRN_DSCR_PRIV and SPRN_DSCR) are defined outside this directory, use them instead. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/dscr/dscr.h | 10 ++++----- tools/testing/selftests/powerpc/reg.h | 35 ++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/dscr/dscr.h b/tools/testing/selftests/powerpc/dscr/dscr.h index a36af1b..18ea223b 100644 --- a/tools/testing/selftests/powerpc/dscr/dscr.h +++ b/tools/testing/selftests/powerpc/dscr/dscr.h @@ -28,8 +28,6 @@ #include "utils.h" -#define SPRN_DSCR 0x11 /* Privilege state SPR */ -#define SPRN_DSCR_USR 0x03 /* Problem state SPR */ #define THREADS 100 /* Max threads */ #define COUNT 100 /* Max iterations */ #define DSCR_MAX 16 /* Max DSCR value */ @@ -48,14 +46,14 @@ inline unsigned long get_dscr(void) { unsigned long ret; - asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR)); + asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_DSCR_PRIV)); return ret; } inline void set_dscr(unsigned long val) { - asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_PRIV)); } /* Problem state DSCR access */ @@ -63,14 +61,14 @@ inline unsigned long get_dscr_usr(void) { unsigned long ret; - asm volatile("mfspr %0,%1" : "=r" (ret): "i" (SPRN_DSCR_USR)); + asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_DSCR)); return ret; } inline void set_dscr_usr(unsigned long val) { - asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR_USR)); + asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); } /* Default DSCR access */ diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h index 65bfdee..bb843b2 100644 --- a/tools/testing/selftests/powerpc/reg.h +++ b/tools/testing/selftests/powerpc/reg.h @@ -46,10 +46,39 @@ #define SPRN_SDAR 781 #define SPRN_SIER 768 -#define SPRN_TEXASR 0x82 +#define SPRN_TEXASR 0x82 /* Transaction Exception and Status Register */ #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ -#define TEXASR_FS 0x08000000 -#define SPRN_TAR 0x32f +#define SPRN_TAR 0x32f /* Target Address Register */ + +#define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ +#define SPRN_DSCR 0x03 /* Data Stream Control Register */ +#define SPRN_PPR 896 /* Program Priority Register */ + +/* TEXASR register bits */ +#define TEXASR_FC 0xFE00000000000000 +#define TEXASR_FP 0x0100000000000000 +#define TEXASR_DA 0x0080000000000000 +#define TEXASR_NO 0x0040000000000000 +#define TEXASR_FO 0x0020000000000000 +#define TEXASR_SIC 0x0010000000000000 +#define TEXASR_NTC 0x0008000000000000 +#define TEXASR_TC 0x0004000000000000 +#define TEXASR_TIC 0x0002000000000000 +#define TEXASR_IC 0x0001000000000000 +#define TEXASR_IFC 0x0000800000000000 +#define TEXASR_ABT 0x0000000100000000 +#define TEXASR_SPD 0x0000000080000000 +#define TEXASR_HV 0x0000000020000000 +#define TEXASR_PR 0x0000000010000000 +#define TEXASR_FS 0x0000000008000000 +#define TEXASR_TE 0x0000000004000000 +#define TEXASR_ROT 0x0000000002000000 + +/* Vector Instructions */ +#define VSX_XX1(xs, ra, rb) (((xs) & 0x1f) << 21 | ((ra) << 16) | \ + ((rb) << 11) | (((xs) >> 5))) +#define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb))) +#define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb))) #endif /* _SELFTESTS_POWERPC_REG_H */ -- cgit v1.1 From 15ec3997aa3bffc461f7b47ca9365d4b0323c671 Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Fri, 30 Sep 2016 10:32:51 +0800 Subject: selftests/powerpc: Move shared headers into new include dir There are some functions, especially register related, which can be shared across multiple selftests/powerpc test directories. This patch creates a new include directory to store those shared files, so that the file layout becomes more neat. Signed-off-by: Simon Guo [mpe: Reworked to move the headers only] Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/Makefile | 2 +- tools/testing/selftests/powerpc/basic_asm.h | 70 ---------------- .../selftests/powerpc/benchmarks/context_switch.c | 2 +- .../testing/selftests/powerpc/copyloops/validate.c | 2 +- tools/testing/selftests/powerpc/fpu_asm.h | 80 ------------------ tools/testing/selftests/powerpc/gpr_asm.h | 96 ---------------------- .../testing/selftests/powerpc/include/basic_asm.h | 73 ++++++++++++++++ tools/testing/selftests/powerpc/include/fpu_asm.h | 80 ++++++++++++++++++ tools/testing/selftests/powerpc/include/gpr_asm.h | 96 ++++++++++++++++++++++ .../selftests/powerpc/include/instructions.h | 68 +++++++++++++++ tools/testing/selftests/powerpc/include/reg.h | 84 +++++++++++++++++++ tools/testing/selftests/powerpc/include/subunit.h | 52 ++++++++++++ tools/testing/selftests/powerpc/include/utils.h | 77 +++++++++++++++++ tools/testing/selftests/powerpc/include/vmx_asm.h | 96 ++++++++++++++++++++++ tools/testing/selftests/powerpc/include/vsx_asm.h | 71 ++++++++++++++++ tools/testing/selftests/powerpc/instructions.h | 68 --------------- tools/testing/selftests/powerpc/math/fpu_asm.S | 4 +- tools/testing/selftests/powerpc/math/vmx_asm.S | 4 +- tools/testing/selftests/powerpc/math/vsx_asm.S | 4 +- tools/testing/selftests/powerpc/reg.h | 84 ------------------- tools/testing/selftests/powerpc/signal/signal.S | 2 +- .../testing/selftests/powerpc/stringloops/memcmp.c | 2 +- tools/testing/selftests/powerpc/subunit.h | 52 ------------ tools/testing/selftests/powerpc/tm/tm-signal.S | 10 +-- tools/testing/selftests/powerpc/tm/tm.h | 2 +- tools/testing/selftests/powerpc/utils.h | 77 ----------------- tools/testing/selftests/powerpc/vmx_asm.h | 96 ---------------------- tools/testing/selftests/powerpc/vsx_asm.h | 71 ---------------- 28 files changed, 714 insertions(+), 711 deletions(-) delete mode 100644 tools/testing/selftests/powerpc/basic_asm.h delete mode 100644 tools/testing/selftests/powerpc/fpu_asm.h delete mode 100644 tools/testing/selftests/powerpc/gpr_asm.h create mode 100644 tools/testing/selftests/powerpc/include/basic_asm.h create mode 100644 tools/testing/selftests/powerpc/include/fpu_asm.h create mode 100644 tools/testing/selftests/powerpc/include/gpr_asm.h create mode 100644 tools/testing/selftests/powerpc/include/instructions.h create mode 100644 tools/testing/selftests/powerpc/include/reg.h create mode 100644 tools/testing/selftests/powerpc/include/subunit.h create mode 100644 tools/testing/selftests/powerpc/include/utils.h create mode 100644 tools/testing/selftests/powerpc/include/vmx_asm.h create mode 100644 tools/testing/selftests/powerpc/include/vsx_asm.h delete mode 100644 tools/testing/selftests/powerpc/instructions.h delete mode 100644 tools/testing/selftests/powerpc/reg.h delete mode 100644 tools/testing/selftests/powerpc/subunit.h delete mode 100644 tools/testing/selftests/powerpc/utils.h delete mode 100644 tools/testing/selftests/powerpc/vmx_asm.h delete mode 100644 tools/testing/selftests/powerpc/vsx_asm.h (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index db54a33..561afa1 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile @@ -8,7 +8,7 @@ ifeq ($(ARCH),powerpc) GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown") -CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS) +CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR)/include $(CFLAGS) export CFLAGS diff --git a/tools/testing/selftests/powerpc/basic_asm.h b/tools/testing/selftests/powerpc/basic_asm.h deleted file mode 100644 index 3349a07..0000000 --- a/tools/testing/selftests/powerpc/basic_asm.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H -#define _SELFTESTS_POWERPC_BASIC_ASM_H - -#include -#include - -#define LOAD_REG_IMMEDIATE(reg,expr) \ - lis reg,(expr)@highest; \ - ori reg,reg,(expr)@higher; \ - rldicr reg,reg,32,31; \ - oris reg,reg,(expr)@high; \ - ori reg,reg,(expr)@l; - -/* - * Note: These macros assume that variables being stored on the stack are - * doublewords, while this is usually the case it may not always be the - * case for each use case. - */ -#if defined(_CALL_ELF) && _CALL_ELF == 2 -#define STACK_FRAME_MIN_SIZE 32 -#define STACK_FRAME_TOC_POS 24 -#define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) -#define __STACK_FRAME_LOCAL(_num_params,_var_num) ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) -#else -#define STACK_FRAME_MIN_SIZE 112 -#define STACK_FRAME_TOC_POS 40 -#define __STACK_FRAME_PARAM(i) (48 + ((i)*8)) - -/* - * Caveat: if a function passed more than 8 doublewords, the caller will have - * made more space... which would render the 112 incorrect. - */ -#define __STACK_FRAME_LOCAL(_num_params,_var_num) (112 + ((_var_num)*8)) -#endif - -/* Parameter x saved to the stack */ -#define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) - -/* Local variable x saved to the stack after x parameters */ -#define STACK_FRAME_LOCAL(num_params,var) __STACK_FRAME_LOCAL(num_params,var) -#define STACK_FRAME_LR_POS 16 -#define STACK_FRAME_CR_POS 8 - -/* - * It is very important to note here that _extra is the extra amount of - * stack space needed. This space can be accessed using STACK_FRAME_PARAM() - * or STACK_FRAME_LOCAL() macros. - * - * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp - * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence - * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets - * preprocessed incorrectly, hence r0. - */ -#define PUSH_BASIC_STACK(_extra) \ - mflr r0; \ - std r0,STACK_FRAME_LR_POS(%r1); \ - stdu %r1,-(_extra + STACK_FRAME_MIN_SIZE)(%r1); \ - mfcr r0; \ - stw r0,STACK_FRAME_CR_POS(%r1); \ - std %r2,STACK_FRAME_TOC_POS(%r1); - -#define POP_BASIC_STACK(_extra) \ - ld %r2,STACK_FRAME_TOC_POS(%r1); \ - lwz r0,STACK_FRAME_CR_POS(%r1); \ - mtcr r0; \ - addi %r1,%r1,(_extra + STACK_FRAME_MIN_SIZE); \ - ld r0,STACK_FRAME_LR_POS(%r1); \ - mtlr r0; - -#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c index a36883a..778f5fb 100644 --- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c +++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c @@ -28,7 +28,7 @@ #ifdef __powerpc__ #include #endif -#include "../utils.h" +#include "utils.h" static unsigned int timeout = 30; diff --git a/tools/testing/selftests/powerpc/copyloops/validate.c b/tools/testing/selftests/powerpc/copyloops/validate.c index 1750ff5..7fb436f 100644 --- a/tools/testing/selftests/powerpc/copyloops/validate.c +++ b/tools/testing/selftests/powerpc/copyloops/validate.c @@ -3,7 +3,7 @@ #include #include -#include "../utils.h" +#include "utils.h" #define MAX_LEN 8192 #define MAX_OFFSET 16 diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/fpu_asm.h deleted file mode 100644 index 6a387d2..0000000 --- a/tools/testing/selftests/powerpc/fpu_asm.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016, Cyril Bur, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _SELFTESTS_POWERPC_FPU_ASM_H -#define _SELFTESTS_POWERPC_FPU_ASM_H -#include "basic_asm.h" - -#define PUSH_FPU(stack_size) \ - stfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ - stfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ - stfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ - stfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ - stfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ - stfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ - stfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ - stfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ - stfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ - stfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ - stfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ - stfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ - stfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ - stfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ - stfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ - stfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ - stfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ - stfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); - -#define POP_FPU(stack_size) \ - lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ - lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ - lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ - lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ - lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ - lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ - lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ - lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ - lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ - lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ - lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ - lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ - lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ - lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ - lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ - lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ - lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ - lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); - -/* - * Careful calling this, it will 'clobber' fpu (by design) - * Don't call this from C - */ -FUNC_START(load_fpu) - lfd f14,0(r3) - lfd f15,8(r3) - lfd f16,16(r3) - lfd f17,24(r3) - lfd f18,32(r3) - lfd f19,40(r3) - lfd f20,48(r3) - lfd f21,56(r3) - lfd f22,64(r3) - lfd f23,72(r3) - lfd f24,80(r3) - lfd f25,88(r3) - lfd f26,96(r3) - lfd f27,104(r3) - lfd f28,112(r3) - lfd f29,120(r3) - lfd f30,128(r3) - lfd f31,136(r3) - blr -FUNC_END(load_fpu) - -#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */ diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/gpr_asm.h deleted file mode 100644 index f6f3885..0000000 --- a/tools/testing/selftests/powerpc/gpr_asm.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2016, Cyril Bur, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _SELFTESTS_POWERPC_GPR_ASM_H -#define _SELFTESTS_POWERPC_GPR_ASM_H - -#include "basic_asm.h" - -#define __PUSH_NVREGS(top_pos); \ - std r31,(top_pos)(%r1); \ - std r30,(top_pos - 8)(%r1); \ - std r29,(top_pos - 16)(%r1); \ - std r28,(top_pos - 24)(%r1); \ - std r27,(top_pos - 32)(%r1); \ - std r26,(top_pos - 40)(%r1); \ - std r25,(top_pos - 48)(%r1); \ - std r24,(top_pos - 56)(%r1); \ - std r23,(top_pos - 64)(%r1); \ - std r22,(top_pos - 72)(%r1); \ - std r21,(top_pos - 80)(%r1); \ - std r20,(top_pos - 88)(%r1); \ - std r19,(top_pos - 96)(%r1); \ - std r18,(top_pos - 104)(%r1); \ - std r17,(top_pos - 112)(%r1); \ - std r16,(top_pos - 120)(%r1); \ - std r15,(top_pos - 128)(%r1); \ - std r14,(top_pos - 136)(%r1) - -#define __POP_NVREGS(top_pos); \ - ld r31,(top_pos)(%r1); \ - ld r30,(top_pos - 8)(%r1); \ - ld r29,(top_pos - 16)(%r1); \ - ld r28,(top_pos - 24)(%r1); \ - ld r27,(top_pos - 32)(%r1); \ - ld r26,(top_pos - 40)(%r1); \ - ld r25,(top_pos - 48)(%r1); \ - ld r24,(top_pos - 56)(%r1); \ - ld r23,(top_pos - 64)(%r1); \ - ld r22,(top_pos - 72)(%r1); \ - ld r21,(top_pos - 80)(%r1); \ - ld r20,(top_pos - 88)(%r1); \ - ld r19,(top_pos - 96)(%r1); \ - ld r18,(top_pos - 104)(%r1); \ - ld r17,(top_pos - 112)(%r1); \ - ld r16,(top_pos - 120)(%r1); \ - ld r15,(top_pos - 128)(%r1); \ - ld r14,(top_pos - 136)(%r1) - -#define PUSH_NVREGS(stack_size) \ - __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) - -/* 18 NV FPU REGS */ -#define PUSH_NVREGS_BELOW_FPU(stack_size) \ - __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) - -#define POP_NVREGS(stack_size) \ - __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) - -/* 18 NV FPU REGS */ -#define POP_NVREGS_BELOW_FPU(stack_size) \ - __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) - -/* - * Careful calling this, it will 'clobber' NVGPRs (by design) - * Don't call this from C - */ -FUNC_START(load_gpr) - ld r14,0(r3) - ld r15,8(r3) - ld r16,16(r3) - ld r17,24(r3) - ld r18,32(r3) - ld r19,40(r3) - ld r20,48(r3) - ld r21,56(r3) - ld r22,64(r3) - ld r23,72(r3) - ld r24,80(r3) - ld r25,88(r3) - ld r26,96(r3) - ld r27,104(r3) - ld r28,112(r3) - ld r29,120(r3) - ld r30,128(r3) - ld r31,136(r3) - blr -FUNC_END(load_gpr) - - -#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */ diff --git a/tools/testing/selftests/powerpc/include/basic_asm.h b/tools/testing/selftests/powerpc/include/basic_asm.h new file mode 100644 index 0000000..12eaddf --- /dev/null +++ b/tools/testing/selftests/powerpc/include/basic_asm.h @@ -0,0 +1,73 @@ +#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H +#define _SELFTESTS_POWERPC_BASIC_ASM_H + +#include +#include + +#define LOAD_REG_IMMEDIATE(reg, expr) \ + lis reg, (expr)@highest; \ + ori reg, reg, (expr)@higher; \ + rldicr reg, reg, 32, 31; \ + oris reg, reg, (expr)@high; \ + ori reg, reg, (expr)@l; + +/* + * Note: These macros assume that variables being stored on the stack are + * doublewords, while this is usually the case it may not always be the + * case for each use case. + */ +#if defined(_CALL_ELF) && _CALL_ELF == 2 +#define STACK_FRAME_MIN_SIZE 32 +#define STACK_FRAME_TOC_POS 24 +#define __STACK_FRAME_PARAM(_param) (32 + ((_param)*8)) +#define __STACK_FRAME_LOCAL(_num_params, _var_num) \ + ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8)) +#else +#define STACK_FRAME_MIN_SIZE 112 +#define STACK_FRAME_TOC_POS 40 +#define __STACK_FRAME_PARAM(i) (48 + ((i)*8)) + +/* + * Caveat: if a function passed more than 8 doublewords, the caller will have + * made more space... which would render the 112 incorrect. + */ +#define __STACK_FRAME_LOCAL(_num_params, _var_num) \ + (112 + ((_var_num)*8)) +#endif + +/* Parameter x saved to the stack */ +#define STACK_FRAME_PARAM(var) __STACK_FRAME_PARAM(var) + +/* Local variable x saved to the stack after x parameters */ +#define STACK_FRAME_LOCAL(num_params, var) \ + __STACK_FRAME_LOCAL(num_params, var) +#define STACK_FRAME_LR_POS 16 +#define STACK_FRAME_CR_POS 8 + +/* + * It is very important to note here that _extra is the extra amount of + * stack space needed. This space can be accessed using STACK_FRAME_PARAM() + * or STACK_FRAME_LOCAL() macros. + * + * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp + * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence + * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets + * preprocessed incorrectly, hence r0. + */ +#define PUSH_BASIC_STACK(_extra) \ + mflr r0; \ + std r0, STACK_FRAME_LR_POS(%r1); \ + stdu %r1, -(_extra + STACK_FRAME_MIN_SIZE)(%r1); \ + mfcr r0; \ + stw r0, STACK_FRAME_CR_POS(%r1); \ + std %r2, STACK_FRAME_TOC_POS(%r1); + +#define POP_BASIC_STACK(_extra) \ + ld %r2, STACK_FRAME_TOC_POS(%r1); \ + lwz r0, STACK_FRAME_CR_POS(%r1); \ + mtcr r0; \ + addi %r1, %r1, (_extra + STACK_FRAME_MIN_SIZE); \ + ld r0, STACK_FRAME_LR_POS(%r1); \ + mtlr r0; + +#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */ diff --git a/tools/testing/selftests/powerpc/include/fpu_asm.h b/tools/testing/selftests/powerpc/include/fpu_asm.h new file mode 100644 index 0000000..6a387d2 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/fpu_asm.h @@ -0,0 +1,80 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SELFTESTS_POWERPC_FPU_ASM_H +#define _SELFTESTS_POWERPC_FPU_ASM_H +#include "basic_asm.h" + +#define PUSH_FPU(stack_size) \ + stfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ + stfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ + stfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ + stfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ + stfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ + stfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ + stfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ + stfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ + stfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ + stfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ + stfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ + stfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ + stfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ + stfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ + stfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ + stfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ + stfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ + stfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); + +#define POP_FPU(stack_size) \ + lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \ + lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \ + lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \ + lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \ + lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \ + lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \ + lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \ + lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \ + lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \ + lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \ + lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \ + lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \ + lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \ + lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \ + lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \ + lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \ + lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \ + lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1); + +/* + * Careful calling this, it will 'clobber' fpu (by design) + * Don't call this from C + */ +FUNC_START(load_fpu) + lfd f14,0(r3) + lfd f15,8(r3) + lfd f16,16(r3) + lfd f17,24(r3) + lfd f18,32(r3) + lfd f19,40(r3) + lfd f20,48(r3) + lfd f21,56(r3) + lfd f22,64(r3) + lfd f23,72(r3) + lfd f24,80(r3) + lfd f25,88(r3) + lfd f26,96(r3) + lfd f27,104(r3) + lfd f28,112(r3) + lfd f29,120(r3) + lfd f30,128(r3) + lfd f31,136(r3) + blr +FUNC_END(load_fpu) + +#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */ diff --git a/tools/testing/selftests/powerpc/include/gpr_asm.h b/tools/testing/selftests/powerpc/include/gpr_asm.h new file mode 100644 index 0000000..f6f3885 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/gpr_asm.h @@ -0,0 +1,96 @@ +/* + * Copyright 2016, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SELFTESTS_POWERPC_GPR_ASM_H +#define _SELFTESTS_POWERPC_GPR_ASM_H + +#include "basic_asm.h" + +#define __PUSH_NVREGS(top_pos); \ + std r31,(top_pos)(%r1); \ + std r30,(top_pos - 8)(%r1); \ + std r29,(top_pos - 16)(%r1); \ + std r28,(top_pos - 24)(%r1); \ + std r27,(top_pos - 32)(%r1); \ + std r26,(top_pos - 40)(%r1); \ + std r25,(top_pos - 48)(%r1); \ + std r24,(top_pos - 56)(%r1); \ + std r23,(top_pos - 64)(%r1); \ + std r22,(top_pos - 72)(%r1); \ + std r21,(top_pos - 80)(%r1); \ + std r20,(top_pos - 88)(%r1); \ + std r19,(top_pos - 96)(%r1); \ + std r18,(top_pos - 104)(%r1); \ + std r17,(top_pos - 112)(%r1); \ + std r16,(top_pos - 120)(%r1); \ + std r15,(top_pos - 128)(%r1); \ + std r14,(top_pos - 136)(%r1) + +#define __POP_NVREGS(top_pos); \ + ld r31,(top_pos)(%r1); \ + ld r30,(top_pos - 8)(%r1); \ + ld r29,(top_pos - 16)(%r1); \ + ld r28,(top_pos - 24)(%r1); \ + ld r27,(top_pos - 32)(%r1); \ + ld r26,(top_pos - 40)(%r1); \ + ld r25,(top_pos - 48)(%r1); \ + ld r24,(top_pos - 56)(%r1); \ + ld r23,(top_pos - 64)(%r1); \ + ld r22,(top_pos - 72)(%r1); \ + ld r21,(top_pos - 80)(%r1); \ + ld r20,(top_pos - 88)(%r1); \ + ld r19,(top_pos - 96)(%r1); \ + ld r18,(top_pos - 104)(%r1); \ + ld r17,(top_pos - 112)(%r1); \ + ld r16,(top_pos - 120)(%r1); \ + ld r15,(top_pos - 128)(%r1); \ + ld r14,(top_pos - 136)(%r1) + +#define PUSH_NVREGS(stack_size) \ + __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) + +/* 18 NV FPU REGS */ +#define PUSH_NVREGS_BELOW_FPU(stack_size) \ + __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) + +#define POP_NVREGS(stack_size) \ + __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE) + +/* 18 NV FPU REGS */ +#define POP_NVREGS_BELOW_FPU(stack_size) \ + __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8)) + +/* + * Careful calling this, it will 'clobber' NVGPRs (by design) + * Don't call this from C + */ +FUNC_START(load_gpr) + ld r14,0(r3) + ld r15,8(r3) + ld r16,16(r3) + ld r17,24(r3) + ld r18,32(r3) + ld r19,40(r3) + ld r20,48(r3) + ld r21,56(r3) + ld r22,64(r3) + ld r23,72(r3) + ld r24,80(r3) + ld r25,88(r3) + ld r26,96(r3) + ld r27,104(r3) + ld r28,112(r3) + ld r29,120(r3) + ld r30,128(r3) + ld r31,136(r3) + blr +FUNC_END(load_gpr) + + +#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */ diff --git a/tools/testing/selftests/powerpc/include/instructions.h b/tools/testing/selftests/powerpc/include/instructions.h new file mode 100644 index 0000000..0fb0bd3 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/instructions.h @@ -0,0 +1,68 @@ +#ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H +#define _SELFTESTS_POWERPC_INSTRUCTIONS_H + +#include +#include + +/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */ +#define __COPY(RA, RB, L) \ + (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10)) +#define COPY(RA, RB, L) \ + .long __COPY((RA), (RB), (L)) + +static inline void copy(void *i) +{ + asm volatile(str(COPY(0, %0, 0))";" + : + : "b" (i) + : "memory" + ); +} + +static inline void copy_first(void *i) +{ + asm volatile(str(COPY(0, %0, 1))";" + : + : "b" (i) + : "memory" + ); +} + +/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */ +#define __PASTE(RA, RB, L, RC) \ + (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31)) +#define PASTE(RA, RB, L, RC) \ + .long __PASTE((RA), (RB), (L), (RC)) + +static inline int paste(void *i) +{ + int cr; + + asm volatile(str(PASTE(0, %1, 0, 0))";" + "mfcr %0;" + : "=r" (cr) + : "b" (i) + : "memory" + ); + return cr; +} + +static inline int paste_last(void *i) +{ + int cr; + + asm volatile(str(PASTE(0, %1, 1, 1))";" + "mfcr %0;" + : "=r" (cr) + : "b" (i) + : "memory" + ); + return cr; +} + +#define PPC_INST_COPY __COPY(0, 0, 0) +#define PPC_INST_COPY_FIRST __COPY(0, 0, 1) +#define PPC_INST_PASTE __PASTE(0, 0, 0, 0) +#define PPC_INST_PASTE_LAST __PASTE(0, 0, 1, 1) + +#endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */ diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h new file mode 100644 index 0000000..bb843b2 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/reg.h @@ -0,0 +1,84 @@ +/* + * Copyright 2014, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_REG_H +#define _SELFTESTS_POWERPC_REG_H + +#define __stringify_1(x) #x +#define __stringify(x) __stringify_1(x) + +#define mfspr(rn) ({unsigned long rval; \ + asm volatile("mfspr %0," _str(rn) \ + : "=r" (rval)); rval; }) +#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \ + : "r" ((unsigned long)(v)) \ + : "memory") + +#define mb() asm volatile("sync" : : : "memory"); + +#define SPRN_MMCR2 769 +#define SPRN_MMCRA 770 +#define SPRN_MMCR0 779 +#define MMCR0_PMAO 0x00000080 +#define MMCR0_PMAE 0x04000000 +#define MMCR0_FC 0x80000000 +#define SPRN_EBBHR 804 +#define SPRN_EBBRR 805 +#define SPRN_BESCR 806 /* Branch event status & control register */ +#define SPRN_BESCRS 800 /* Branch event status & control set (1 bits set to 1) */ +#define SPRN_BESCRSU 801 /* Branch event status & control set upper */ +#define SPRN_BESCRR 802 /* Branch event status & control REset (1 bits set to 0) */ +#define SPRN_BESCRRU 803 /* Branch event status & control REset upper */ + +#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ +#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ + +#define SPRN_PMC1 771 +#define SPRN_PMC2 772 +#define SPRN_PMC3 773 +#define SPRN_PMC4 774 +#define SPRN_PMC5 775 +#define SPRN_PMC6 776 + +#define SPRN_SIAR 780 +#define SPRN_SDAR 781 +#define SPRN_SIER 768 + +#define SPRN_TEXASR 0x82 /* Transaction Exception and Status Register */ +#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ +#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ +#define SPRN_TAR 0x32f /* Target Address Register */ + +#define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ +#define SPRN_DSCR 0x03 /* Data Stream Control Register */ +#define SPRN_PPR 896 /* Program Priority Register */ + +/* TEXASR register bits */ +#define TEXASR_FC 0xFE00000000000000 +#define TEXASR_FP 0x0100000000000000 +#define TEXASR_DA 0x0080000000000000 +#define TEXASR_NO 0x0040000000000000 +#define TEXASR_FO 0x0020000000000000 +#define TEXASR_SIC 0x0010000000000000 +#define TEXASR_NTC 0x0008000000000000 +#define TEXASR_TC 0x0004000000000000 +#define TEXASR_TIC 0x0002000000000000 +#define TEXASR_IC 0x0001000000000000 +#define TEXASR_IFC 0x0000800000000000 +#define TEXASR_ABT 0x0000000100000000 +#define TEXASR_SPD 0x0000000080000000 +#define TEXASR_HV 0x0000000020000000 +#define TEXASR_PR 0x0000000010000000 +#define TEXASR_FS 0x0000000008000000 +#define TEXASR_TE 0x0000000004000000 +#define TEXASR_ROT 0x0000000002000000 + +/* Vector Instructions */ +#define VSX_XX1(xs, ra, rb) (((xs) & 0x1f) << 21 | ((ra) << 16) | \ + ((rb) << 11) | (((xs) >> 5))) +#define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb))) +#define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb))) + +#endif /* _SELFTESTS_POWERPC_REG_H */ diff --git a/tools/testing/selftests/powerpc/include/subunit.h b/tools/testing/selftests/powerpc/include/subunit.h new file mode 100644 index 0000000..9c6c4e9 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/subunit.h @@ -0,0 +1,52 @@ +/* + * Copyright 2013, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_SUBUNIT_H +#define _SELFTESTS_POWERPC_SUBUNIT_H + +static inline void test_start(char *name) +{ + printf("test: %s\n", name); +} + +static inline void test_failure_detail(char *name, char *detail) +{ + printf("failure: %s [%s]\n", name, detail); +} + +static inline void test_failure(char *name) +{ + printf("failure: %s\n", name); +} + +static inline void test_error(char *name) +{ + printf("error: %s\n", name); +} + +static inline void test_skip(char *name) +{ + printf("skip: %s\n", name); +} + +static inline void test_success(char *name) +{ + printf("success: %s\n", name); +} + +static inline void test_finish(char *name, int status) +{ + if (status) + test_failure(name); + else + test_success(name); +} + +static inline void test_set_git_version(char *value) +{ + printf("tags: git_version:%s\n", value); +} + +#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */ diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h new file mode 100644 index 0000000..53405e8 --- /dev/null +++ b/tools/testing/selftests/powerpc/include/utils.h @@ -0,0 +1,77 @@ +/* + * Copyright 2013, Michael Ellerman, IBM Corp. + * Licensed under GPLv2. + */ + +#ifndef _SELFTESTS_POWERPC_UTILS_H +#define _SELFTESTS_POWERPC_UTILS_H + +#define __cacheline_aligned __attribute__((aligned(128))) + +#include +#include +#include +#include "reg.h" + +/* Avoid headaches with PRI?64 - just use %ll? always */ +typedef unsigned long long u64; +typedef signed long long s64; + +/* Just for familiarity */ +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +void test_harness_set_timeout(uint64_t time); +int test_harness(int (test_function)(void), char *name); +extern void *get_auxv_entry(int type); +int pick_online_cpu(void); + +static inline bool have_hwcap(unsigned long ftr) +{ + return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; +} + +#ifdef AT_HWCAP2 +static inline bool have_hwcap2(unsigned long ftr2) +{ + return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; +} +#else +static inline bool have_hwcap2(unsigned long ftr2) +{ + return false; +} +#endif + +/* Yes, this is evil */ +#define FAIL_IF(x) \ +do { \ + if ((x)) { \ + fprintf(stderr, \ + "[FAIL] Test FAILED on line %d\n", __LINE__); \ + return 1; \ + } \ +} while (0) + +/* The test harness uses this, yes it's gross */ +#define MAGIC_SKIP_RETURN_VALUE 99 + +#define SKIP_IF(x) \ +do { \ + if ((x)) { \ + fprintf(stderr, \ + "[SKIP] Test skipped on line %d\n", __LINE__); \ + return MAGIC_SKIP_RETURN_VALUE; \ + } \ +} while (0) + +#define _str(s) #s +#define str(s) _str(s) + +/* POWER9 feature */ +#ifndef PPC_FEATURE2_ARCH_3_00 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#endif + +#endif /* _SELFTESTS_POWERPC_UTILS_H */ diff --git a/tools/testing/selftests/powerpc/include/vmx_asm.h b/tools/testing/selftests/powerpc/include/vmx_asm.h new file mode 100644 index 0000000..2eaaeca --- /dev/null +++ b/tools/testing/selftests/powerpc/include/vmx_asm.h @@ -0,0 +1,96 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "basic_asm.h" + +/* POS MUST BE 16 ALIGNED! */ +#define PUSH_VMX(pos,reg) \ + li reg,pos; \ + stvx v20,reg,%r1; \ + addi reg,reg,16; \ + stvx v21,reg,%r1; \ + addi reg,reg,16; \ + stvx v22,reg,%r1; \ + addi reg,reg,16; \ + stvx v23,reg,%r1; \ + addi reg,reg,16; \ + stvx v24,reg,%r1; \ + addi reg,reg,16; \ + stvx v25,reg,%r1; \ + addi reg,reg,16; \ + stvx v26,reg,%r1; \ + addi reg,reg,16; \ + stvx v27,reg,%r1; \ + addi reg,reg,16; \ + stvx v28,reg,%r1; \ + addi reg,reg,16; \ + stvx v29,reg,%r1; \ + addi reg,reg,16; \ + stvx v30,reg,%r1; \ + addi reg,reg,16; \ + stvx v31,reg,%r1; + +/* POS MUST BE 16 ALIGNED! */ +#define POP_VMX(pos,reg) \ + li reg,pos; \ + lvx v20,reg,%r1; \ + addi reg,reg,16; \ + lvx v21,reg,%r1; \ + addi reg,reg,16; \ + lvx v22,reg,%r1; \ + addi reg,reg,16; \ + lvx v23,reg,%r1; \ + addi reg,reg,16; \ + lvx v24,reg,%r1; \ + addi reg,reg,16; \ + lvx v25,reg,%r1; \ + addi reg,reg,16; \ + lvx v26,reg,%r1; \ + addi reg,reg,16; \ + lvx v27,reg,%r1; \ + addi reg,reg,16; \ + lvx v28,reg,%r1; \ + addi reg,reg,16; \ + lvx v29,reg,%r1; \ + addi reg,reg,16; \ + lvx v30,reg,%r1; \ + addi reg,reg,16; \ + lvx v31,reg,%r1; + +/* + * Careful this will 'clobber' vmx (by design) + * Don't call this from C + */ +FUNC_START(load_vmx) + li r5,0 + lvx v20,r5,r3 + addi r5,r5,16 + lvx v21,r5,r3 + addi r5,r5,16 + lvx v22,r5,r3 + addi r5,r5,16 + lvx v23,r5,r3 + addi r5,r5,16 + lvx v24,r5,r3 + addi r5,r5,16 + lvx v25,r5,r3 + addi r5,r5,16 + lvx v26,r5,r3 + addi r5,r5,16 + lvx v27,r5,r3 + addi r5,r5,16 + lvx v28,r5,r3 + addi r5,r5,16 + lvx v29,r5,r3 + addi r5,r5,16 + lvx v30,r5,r3 + addi r5,r5,16 + lvx v31,r5,r3 + blr +FUNC_END(load_vmx) diff --git a/tools/testing/selftests/powerpc/include/vsx_asm.h b/tools/testing/selftests/powerpc/include/vsx_asm.h new file mode 100644 index 0000000..d828bfb --- /dev/null +++ b/tools/testing/selftests/powerpc/include/vsx_asm.h @@ -0,0 +1,71 @@ +/* + * Copyright 2015, Cyril Bur, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "basic_asm.h" + +/* + * Careful this will 'clobber' vsx (by design), VSX are always + * volatile though so unlike vmx this isn't so much of an issue + * Still should avoid calling from C + */ +FUNC_START(load_vsx) + li r5,0 + lxvx vs20,r5,r3 + addi r5,r5,16 + lxvx vs21,r5,r3 + addi r5,r5,16 + lxvx vs22,r5,r3 + addi r5,r5,16 + lxvx vs23,r5,r3 + addi r5,r5,16 + lxvx vs24,r5,r3 + addi r5,r5,16 + lxvx vs25,r5,r3 + addi r5,r5,16 + lxvx vs26,r5,r3 + addi r5,r5,16 + lxvx vs27,r5,r3 + addi r5,r5,16 + lxvx vs28,r5,r3 + addi r5,r5,16 + lxvx vs29,r5,r3 + addi r5,r5,16 + lxvx vs30,r5,r3 + addi r5,r5,16 + lxvx vs31,r5,r3 + blr +FUNC_END(load_vsx) + +FUNC_START(store_vsx) + li r5,0 + stxvx vs20,r5,r3 + addi r5,r5,16 + stxvx vs21,r5,r3 + addi r5,r5,16 + stxvx vs22,r5,r3 + addi r5,r5,16 + stxvx vs23,r5,r3 + addi r5,r5,16 + stxvx vs24,r5,r3 + addi r5,r5,16 + stxvx vs25,r5,r3 + addi r5,r5,16 + stxvx vs26,r5,r3 + addi r5,r5,16 + stxvx vs27,r5,r3 + addi r5,r5,16 + stxvx vs28,r5,r3 + addi r5,r5,16 + stxvx vs29,r5,r3 + addi r5,r5,16 + stxvx vs30,r5,r3 + addi r5,r5,16 + stxvx vs31,r5,r3 + blr +FUNC_END(store_vsx) diff --git a/tools/testing/selftests/powerpc/instructions.h b/tools/testing/selftests/powerpc/instructions.h deleted file mode 100644 index 0fb0bd3..0000000 --- a/tools/testing/selftests/powerpc/instructions.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H -#define _SELFTESTS_POWERPC_INSTRUCTIONS_H - -#include -#include - -/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */ -#define __COPY(RA, RB, L) \ - (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10)) -#define COPY(RA, RB, L) \ - .long __COPY((RA), (RB), (L)) - -static inline void copy(void *i) -{ - asm volatile(str(COPY(0, %0, 0))";" - : - : "b" (i) - : "memory" - ); -} - -static inline void copy_first(void *i) -{ - asm volatile(str(COPY(0, %0, 1))";" - : - : "b" (i) - : "memory" - ); -} - -/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */ -#define __PASTE(RA, RB, L, RC) \ - (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31)) -#define PASTE(RA, RB, L, RC) \ - .long __PASTE((RA), (RB), (L), (RC)) - -static inline int paste(void *i) -{ - int cr; - - asm volatile(str(PASTE(0, %1, 0, 0))";" - "mfcr %0;" - : "=r" (cr) - : "b" (i) - : "memory" - ); - return cr; -} - -static inline int paste_last(void *i) -{ - int cr; - - asm volatile(str(PASTE(0, %1, 1, 1))";" - "mfcr %0;" - : "=r" (cr) - : "b" (i) - : "memory" - ); - return cr; -} - -#define PPC_INST_COPY __COPY(0, 0, 0) -#define PPC_INST_COPY_FIRST __COPY(0, 0, 1) -#define PPC_INST_PASTE __PASTE(0, 0, 0, 0) -#define PPC_INST_PASTE_LAST __PASTE(0, 0, 1, 1) - -#endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */ diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S index 241f067..8a04bb1 100644 --- a/tools/testing/selftests/powerpc/math/fpu_asm.S +++ b/tools/testing/selftests/powerpc/math/fpu_asm.S @@ -7,8 +7,8 @@ * 2 of the License, or (at your option) any later version. */ -#include "../basic_asm.h" -#include "../fpu_asm.h" +#include "basic_asm.h" +#include "fpu_asm.h" FUNC_START(check_fpu) mr r4,r3 diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S index fd74da4..cb1e5ae 100644 --- a/tools/testing/selftests/powerpc/math/vmx_asm.S +++ b/tools/testing/selftests/powerpc/math/vmx_asm.S @@ -7,8 +7,8 @@ * 2 of the License, or (at your option) any later version. */ -#include "../basic_asm.h" -#include "../vmx_asm.h" +#include "basic_asm.h" +#include "vmx_asm.h" # Should be safe from C, only touches r4, r5 and v0,v1,v2 FUNC_START(check_vmx) diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S index a110dd8..8f431f6 100644 --- a/tools/testing/selftests/powerpc/math/vsx_asm.S +++ b/tools/testing/selftests/powerpc/math/vsx_asm.S @@ -7,8 +7,8 @@ * 2 of the License, or (at your option) any later version. */ -#include "../basic_asm.h" -#include "../vsx_asm.h" +#include "basic_asm.h" +#include "vsx_asm.h" #long check_vsx(vector int *r3); #This function wraps storeing VSX regs to the end of an array and a diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h deleted file mode 100644 index bb843b2..0000000 --- a/tools/testing/selftests/powerpc/reg.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2014, Michael Ellerman, IBM Corp. - * Licensed under GPLv2. - */ - -#ifndef _SELFTESTS_POWERPC_REG_H -#define _SELFTESTS_POWERPC_REG_H - -#define __stringify_1(x) #x -#define __stringify(x) __stringify_1(x) - -#define mfspr(rn) ({unsigned long rval; \ - asm volatile("mfspr %0," _str(rn) \ - : "=r" (rval)); rval; }) -#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \ - : "r" ((unsigned long)(v)) \ - : "memory") - -#define mb() asm volatile("sync" : : : "memory"); - -#define SPRN_MMCR2 769 -#define SPRN_MMCRA 770 -#define SPRN_MMCR0 779 -#define MMCR0_PMAO 0x00000080 -#define MMCR0_PMAE 0x04000000 -#define MMCR0_FC 0x80000000 -#define SPRN_EBBHR 804 -#define SPRN_EBBRR 805 -#define SPRN_BESCR 806 /* Branch event status & control register */ -#define SPRN_BESCRS 800 /* Branch event status & control set (1 bits set to 1) */ -#define SPRN_BESCRSU 801 /* Branch event status & control set upper */ -#define SPRN_BESCRR 802 /* Branch event status & control REset (1 bits set to 0) */ -#define SPRN_BESCRRU 803 /* Branch event status & control REset upper */ - -#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ -#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ - -#define SPRN_PMC1 771 -#define SPRN_PMC2 772 -#define SPRN_PMC3 773 -#define SPRN_PMC4 774 -#define SPRN_PMC5 775 -#define SPRN_PMC6 776 - -#define SPRN_SIAR 780 -#define SPRN_SDAR 781 -#define SPRN_SIER 768 - -#define SPRN_TEXASR 0x82 /* Transaction Exception and Status Register */ -#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ -#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ -#define SPRN_TAR 0x32f /* Target Address Register */ - -#define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ -#define SPRN_DSCR 0x03 /* Data Stream Control Register */ -#define SPRN_PPR 896 /* Program Priority Register */ - -/* TEXASR register bits */ -#define TEXASR_FC 0xFE00000000000000 -#define TEXASR_FP 0x0100000000000000 -#define TEXASR_DA 0x0080000000000000 -#define TEXASR_NO 0x0040000000000000 -#define TEXASR_FO 0x0020000000000000 -#define TEXASR_SIC 0x0010000000000000 -#define TEXASR_NTC 0x0008000000000000 -#define TEXASR_TC 0x0004000000000000 -#define TEXASR_TIC 0x0002000000000000 -#define TEXASR_IC 0x0001000000000000 -#define TEXASR_IFC 0x0000800000000000 -#define TEXASR_ABT 0x0000000100000000 -#define TEXASR_SPD 0x0000000080000000 -#define TEXASR_HV 0x0000000020000000 -#define TEXASR_PR 0x0000000010000000 -#define TEXASR_FS 0x0000000008000000 -#define TEXASR_TE 0x0000000004000000 -#define TEXASR_ROT 0x0000000002000000 - -/* Vector Instructions */ -#define VSX_XX1(xs, ra, rb) (((xs) & 0x1f) << 21 | ((ra) << 16) | \ - ((rb) << 11) | (((xs) >> 5))) -#define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb))) -#define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb))) - -#endif /* _SELFTESTS_POWERPC_REG_H */ diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S index 7043d52..322f2f1 100644 --- a/tools/testing/selftests/powerpc/signal/signal.S +++ b/tools/testing/selftests/powerpc/signal/signal.S @@ -7,7 +7,7 @@ * 2 of the License, or (at your option) any later version. */ -#include "../basic_asm.h" +#include "basic_asm.h" /* long signal_self(pid_t pid, int sig); */ FUNC_START(signal_self) diff --git a/tools/testing/selftests/powerpc/stringloops/memcmp.c b/tools/testing/selftests/powerpc/stringloops/memcmp.c index 17417dd..30b1222 100644 --- a/tools/testing/selftests/powerpc/stringloops/memcmp.c +++ b/tools/testing/selftests/powerpc/stringloops/memcmp.c @@ -1,7 +1,7 @@ #include #include #include -#include "../utils.h" +#include "utils.h" #define SIZE 256 #define ITERATIONS 10000 diff --git a/tools/testing/selftests/powerpc/subunit.h b/tools/testing/selftests/powerpc/subunit.h deleted file mode 100644 index 9c6c4e9..0000000 --- a/tools/testing/selftests/powerpc/subunit.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013, Michael Ellerman, IBM Corp. - * Licensed under GPLv2. - */ - -#ifndef _SELFTESTS_POWERPC_SUBUNIT_H -#define _SELFTESTS_POWERPC_SUBUNIT_H - -static inline void test_start(char *name) -{ - printf("test: %s\n", name); -} - -static inline void test_failure_detail(char *name, char *detail) -{ - printf("failure: %s [%s]\n", name, detail); -} - -static inline void test_failure(char *name) -{ - printf("failure: %s\n", name); -} - -static inline void test_error(char *name) -{ - printf("error: %s\n", name); -} - -static inline void test_skip(char *name) -{ - printf("skip: %s\n", name); -} - -static inline void test_success(char *name) -{ - printf("success: %s\n", name); -} - -static inline void test_finish(char *name, int status) -{ - if (status) - test_failure(name); - else - test_success(name); -} - -static inline void test_set_git_version(char *value) -{ - printf("tags: git_version:%s\n", value); -} - -#endif /* _SELFTESTS_POWERPC_SUBUNIT_H */ diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S index 4e13e8b..506a4eb 100644 --- a/tools/testing/selftests/powerpc/tm/tm-signal.S +++ b/tools/testing/selftests/powerpc/tm/tm-signal.S @@ -7,11 +7,11 @@ * 2 of the License, or (at your option) any later version. */ -#include "../basic_asm.h" -#include "../gpr_asm.h" -#include "../fpu_asm.h" -#include "../vmx_asm.h" -#include "../vsx_asm.h" +#include "basic_asm.h" +#include "gpr_asm.h" +#include "fpu_asm.h" +#include "vmx_asm.h" +#include "vsx_asm.h" /* * Large caveat here being that the caller cannot expect the diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h index 2c8da74..0ffff04 100644 --- a/tools/testing/selftests/powerpc/tm/tm.h +++ b/tools/testing/selftests/powerpc/tm/tm.h @@ -10,7 +10,7 @@ #include #include -#include "../utils.h" +#include "utils.h" static inline bool have_htm(void) { diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h deleted file mode 100644 index 53405e8..0000000 --- a/tools/testing/selftests/powerpc/utils.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2013, Michael Ellerman, IBM Corp. - * Licensed under GPLv2. - */ - -#ifndef _SELFTESTS_POWERPC_UTILS_H -#define _SELFTESTS_POWERPC_UTILS_H - -#define __cacheline_aligned __attribute__((aligned(128))) - -#include -#include -#include -#include "reg.h" - -/* Avoid headaches with PRI?64 - just use %ll? always */ -typedef unsigned long long u64; -typedef signed long long s64; - -/* Just for familiarity */ -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -void test_harness_set_timeout(uint64_t time); -int test_harness(int (test_function)(void), char *name); -extern void *get_auxv_entry(int type); -int pick_online_cpu(void); - -static inline bool have_hwcap(unsigned long ftr) -{ - return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; -} - -#ifdef AT_HWCAP2 -static inline bool have_hwcap2(unsigned long ftr2) -{ - return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; -} -#else -static inline bool have_hwcap2(unsigned long ftr2) -{ - return false; -} -#endif - -/* Yes, this is evil */ -#define FAIL_IF(x) \ -do { \ - if ((x)) { \ - fprintf(stderr, \ - "[FAIL] Test FAILED on line %d\n", __LINE__); \ - return 1; \ - } \ -} while (0) - -/* The test harness uses this, yes it's gross */ -#define MAGIC_SKIP_RETURN_VALUE 99 - -#define SKIP_IF(x) \ -do { \ - if ((x)) { \ - fprintf(stderr, \ - "[SKIP] Test skipped on line %d\n", __LINE__); \ - return MAGIC_SKIP_RETURN_VALUE; \ - } \ -} while (0) - -#define _str(s) #s -#define str(s) _str(s) - -/* POWER9 feature */ -#ifndef PPC_FEATURE2_ARCH_3_00 -#define PPC_FEATURE2_ARCH_3_00 0x00800000 -#endif - -#endif /* _SELFTESTS_POWERPC_UTILS_H */ diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/vmx_asm.h deleted file mode 100644 index 2eaaeca..0000000 --- a/tools/testing/selftests/powerpc/vmx_asm.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2015, Cyril Bur, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include "basic_asm.h" - -/* POS MUST BE 16 ALIGNED! */ -#define PUSH_VMX(pos,reg) \ - li reg,pos; \ - stvx v20,reg,%r1; \ - addi reg,reg,16; \ - stvx v21,reg,%r1; \ - addi reg,reg,16; \ - stvx v22,reg,%r1; \ - addi reg,reg,16; \ - stvx v23,reg,%r1; \ - addi reg,reg,16; \ - stvx v24,reg,%r1; \ - addi reg,reg,16; \ - stvx v25,reg,%r1; \ - addi reg,reg,16; \ - stvx v26,reg,%r1; \ - addi reg,reg,16; \ - stvx v27,reg,%r1; \ - addi reg,reg,16; \ - stvx v28,reg,%r1; \ - addi reg,reg,16; \ - stvx v29,reg,%r1; \ - addi reg,reg,16; \ - stvx v30,reg,%r1; \ - addi reg,reg,16; \ - stvx v31,reg,%r1; - -/* POS MUST BE 16 ALIGNED! */ -#define POP_VMX(pos,reg) \ - li reg,pos; \ - lvx v20,reg,%r1; \ - addi reg,reg,16; \ - lvx v21,reg,%r1; \ - addi reg,reg,16; \ - lvx v22,reg,%r1; \ - addi reg,reg,16; \ - lvx v23,reg,%r1; \ - addi reg,reg,16; \ - lvx v24,reg,%r1; \ - addi reg,reg,16; \ - lvx v25,reg,%r1; \ - addi reg,reg,16; \ - lvx v26,reg,%r1; \ - addi reg,reg,16; \ - lvx v27,reg,%r1; \ - addi reg,reg,16; \ - lvx v28,reg,%r1; \ - addi reg,reg,16; \ - lvx v29,reg,%r1; \ - addi reg,reg,16; \ - lvx v30,reg,%r1; \ - addi reg,reg,16; \ - lvx v31,reg,%r1; - -/* - * Careful this will 'clobber' vmx (by design) - * Don't call this from C - */ -FUNC_START(load_vmx) - li r5,0 - lvx v20,r5,r3 - addi r5,r5,16 - lvx v21,r5,r3 - addi r5,r5,16 - lvx v22,r5,r3 - addi r5,r5,16 - lvx v23,r5,r3 - addi r5,r5,16 - lvx v24,r5,r3 - addi r5,r5,16 - lvx v25,r5,r3 - addi r5,r5,16 - lvx v26,r5,r3 - addi r5,r5,16 - lvx v27,r5,r3 - addi r5,r5,16 - lvx v28,r5,r3 - addi r5,r5,16 - lvx v29,r5,r3 - addi r5,r5,16 - lvx v30,r5,r3 - addi r5,r5,16 - lvx v31,r5,r3 - blr -FUNC_END(load_vmx) diff --git a/tools/testing/selftests/powerpc/vsx_asm.h b/tools/testing/selftests/powerpc/vsx_asm.h deleted file mode 100644 index d828bfb..0000000 --- a/tools/testing/selftests/powerpc/vsx_asm.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2015, Cyril Bur, IBM Corp. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include "basic_asm.h" - -/* - * Careful this will 'clobber' vsx (by design), VSX are always - * volatile though so unlike vmx this isn't so much of an issue - * Still should avoid calling from C - */ -FUNC_START(load_vsx) - li r5,0 - lxvx vs20,r5,r3 - addi r5,r5,16 - lxvx vs21,r5,r3 - addi r5,r5,16 - lxvx vs22,r5,r3 - addi r5,r5,16 - lxvx vs23,r5,r3 - addi r5,r5,16 - lxvx vs24,r5,r3 - addi r5,r5,16 - lxvx vs25,r5,r3 - addi r5,r5,16 - lxvx vs26,r5,r3 - addi r5,r5,16 - lxvx vs27,r5,r3 - addi r5,r5,16 - lxvx vs28,r5,r3 - addi r5,r5,16 - lxvx vs29,r5,r3 - addi r5,r5,16 - lxvx vs30,r5,r3 - addi r5,r5,16 - lxvx vs31,r5,r3 - blr -FUNC_END(load_vsx) - -FUNC_START(store_vsx) - li r5,0 - stxvx vs20,r5,r3 - addi r5,r5,16 - stxvx vs21,r5,r3 - addi r5,r5,16 - stxvx vs22,r5,r3 - addi r5,r5,16 - stxvx vs23,r5,r3 - addi r5,r5,16 - stxvx vs24,r5,r3 - addi r5,r5,16 - stxvx vs25,r5,r3 - addi r5,r5,16 - stxvx vs26,r5,r3 - addi r5,r5,16 - stxvx vs27,r5,r3 - addi r5,r5,16 - stxvx vs28,r5,r3 - addi r5,r5,16 - stxvx vs29,r5,r3 - addi r5,r5,16 - stxvx vs30,r5,r3 - addi r5,r5,16 - stxvx vs31,r5,r3 - blr -FUNC_END(store_vsx) -- cgit v1.1 From f666ad413db6f7fbfaeec6b11ed6f8e4b60dda38 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:52 +0800 Subject: selftests/powerpc: Add ptrace tests for GPR/FPR registers This patch adds ptrace interface test for GPR/FPR registers. This adds ptrace interface based helper functions related to GPR/FPR access and some assembly helper functions related to GPR/FPR registers. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo [mpe: Add #defines for the new note types when headers don't define them] Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/Makefile | 3 +- tools/testing/selftests/powerpc/include/reg.h | 61 ++++ tools/testing/selftests/powerpc/lib/reg.S | 132 ++++++++ tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 12 + .../testing/selftests/powerpc/ptrace/ptrace-gpr.c | 123 +++++++ .../testing/selftests/powerpc/ptrace/ptrace-gpr.h | 74 ++++ tools/testing/selftests/powerpc/ptrace/ptrace.h | 376 +++++++++++++++++++++ 8 files changed, 781 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/lib/reg.S create mode 100644 tools/testing/selftests/powerpc/ptrace/.gitignore create mode 100644 tools/testing/selftests/powerpc/ptrace/Makefile create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace.h (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 561afa1..c2c4211 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile @@ -26,7 +26,8 @@ SUB_DIRS = alignment \ syscalls \ tm \ vphn \ - math + math \ + ptrace endif diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h index bb843b2..4afdebc 100644 --- a/tools/testing/selftests/powerpc/include/reg.h +++ b/tools/testing/selftests/powerpc/include/reg.h @@ -81,4 +81,65 @@ #define STXVD2X(xs, ra, rb) .long (0x7c000798 | VSX_XX1((xs), (ra), (rb))) #define LXVD2X(xs, ra, rb) .long (0x7c000698 | VSX_XX1((xs), (ra), (rb))) +#define ASM_LOAD_GPR_IMMED(_asm_symbol_name_immed) \ + "li 14, %[" #_asm_symbol_name_immed "];" \ + "li 15, %[" #_asm_symbol_name_immed "];" \ + "li 16, %[" #_asm_symbol_name_immed "];" \ + "li 17, %[" #_asm_symbol_name_immed "];" \ + "li 18, %[" #_asm_symbol_name_immed "];" \ + "li 19, %[" #_asm_symbol_name_immed "];" \ + "li 20, %[" #_asm_symbol_name_immed "];" \ + "li 21, %[" #_asm_symbol_name_immed "];" \ + "li 22, %[" #_asm_symbol_name_immed "];" \ + "li 23, %[" #_asm_symbol_name_immed "];" \ + "li 24, %[" #_asm_symbol_name_immed "];" \ + "li 25, %[" #_asm_symbol_name_immed "];" \ + "li 26, %[" #_asm_symbol_name_immed "];" \ + "li 27, %[" #_asm_symbol_name_immed "];" \ + "li 28, %[" #_asm_symbol_name_immed "];" \ + "li 29, %[" #_asm_symbol_name_immed "];" \ + "li 30, %[" #_asm_symbol_name_immed "];" \ + "li 31, %[" #_asm_symbol_name_immed "];" + +#define ASM_LOAD_FPR_SINGLE_PRECISION(_asm_symbol_name_addr) \ + "lfs 0, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 1, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 2, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 3, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 4, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 5, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 6, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 7, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 8, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 9, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 10, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 11, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 12, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 13, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 14, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 15, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 16, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 17, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 18, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 19, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 20, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 21, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 22, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 23, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 24, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 25, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 26, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 27, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 28, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 29, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 30, 0(%[" #_asm_symbol_name_addr "]);" \ + "lfs 31, 0(%[" #_asm_symbol_name_addr "]);" + +#ifndef __ASSEMBLER__ +void store_gpr(unsigned long *addr); +void load_gpr(unsigned long *addr); +void load_fpr_single_precision(float *addr); +void store_fpr_single_precision(float *addr); +#endif /* end of __ASSEMBLER__ */ + #endif /* _SELFTESTS_POWERPC_REG_H */ diff --git a/tools/testing/selftests/powerpc/lib/reg.S b/tools/testing/selftests/powerpc/lib/reg.S new file mode 100644 index 0000000..b6aee2f --- /dev/null +++ b/tools/testing/selftests/powerpc/lib/reg.S @@ -0,0 +1,132 @@ +/* + * test helper assembly functions + * + * Copyright (C) 2016 Simon Guo, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include "reg.h" + + +/* Non volatile GPR - unsigned long buf[18] */ +FUNC_START(load_gpr) + ld 14, 0*8(3) + ld 15, 1*8(3) + ld 16, 2*8(3) + ld 17, 3*8(3) + ld 18, 4*8(3) + ld 19, 5*8(3) + ld 20, 6*8(3) + ld 21, 7*8(3) + ld 22, 8*8(3) + ld 23, 9*8(3) + ld 24, 10*8(3) + ld 25, 11*8(3) + ld 26, 12*8(3) + ld 27, 13*8(3) + ld 28, 14*8(3) + ld 29, 15*8(3) + ld 30, 16*8(3) + ld 31, 17*8(3) + blr +FUNC_END(load_gpr) + +FUNC_START(store_gpr) + std 14, 0*8(3) + std 15, 1*8(3) + std 16, 2*8(3) + std 17, 3*8(3) + std 18, 4*8(3) + std 19, 5*8(3) + std 20, 6*8(3) + std 21, 7*8(3) + std 22, 8*8(3) + std 23, 9*8(3) + std 24, 10*8(3) + std 25, 11*8(3) + std 26, 12*8(3) + std 27, 13*8(3) + std 28, 14*8(3) + std 29, 15*8(3) + std 30, 16*8(3) + std 31, 17*8(3) + blr +FUNC_END(store_gpr) + +/* Single Precision Float - float buf[32] */ +FUNC_START(load_fpr_single_precision) + lfs 0, 0*4(3) + lfs 1, 1*4(3) + lfs 2, 2*4(3) + lfs 3, 3*4(3) + lfs 4, 4*4(3) + lfs 5, 5*4(3) + lfs 6, 6*4(3) + lfs 7, 7*4(3) + lfs 8, 8*4(3) + lfs 9, 9*4(3) + lfs 10, 10*4(3) + lfs 11, 11*4(3) + lfs 12, 12*4(3) + lfs 13, 13*4(3) + lfs 14, 14*4(3) + lfs 15, 15*4(3) + lfs 16, 16*4(3) + lfs 17, 17*4(3) + lfs 18, 18*4(3) + lfs 19, 19*4(3) + lfs 20, 20*4(3) + lfs 21, 21*4(3) + lfs 22, 22*4(3) + lfs 23, 23*4(3) + lfs 24, 24*4(3) + lfs 25, 25*4(3) + lfs 26, 26*4(3) + lfs 27, 27*4(3) + lfs 28, 28*4(3) + lfs 29, 29*4(3) + lfs 30, 30*4(3) + lfs 31, 31*4(3) + blr +FUNC_END(load_fpr_single_precision) + +/* Single Precision Float - float buf[32] */ +FUNC_START(store_fpr_single_precision) + stfs 0, 0*4(3) + stfs 1, 1*4(3) + stfs 2, 2*4(3) + stfs 3, 3*4(3) + stfs 4, 4*4(3) + stfs 5, 5*4(3) + stfs 6, 6*4(3) + stfs 7, 7*4(3) + stfs 8, 8*4(3) + stfs 9, 9*4(3) + stfs 10, 10*4(3) + stfs 11, 11*4(3) + stfs 12, 12*4(3) + stfs 13, 13*4(3) + stfs 14, 14*4(3) + stfs 15, 15*4(3) + stfs 16, 16*4(3) + stfs 17, 17*4(3) + stfs 18, 18*4(3) + stfs 19, 19*4(3) + stfs 20, 20*4(3) + stfs 21, 21*4(3) + stfs 22, 22*4(3) + stfs 23, 23*4(3) + stfs 24, 24*4(3) + stfs 25, 25*4(3) + stfs 26, 26*4(3) + stfs 27, 27*4(3) + stfs 28, 28*4(3) + stfs 29, 29*4(3) + stfs 30, 30*4(3) + stfs 31, 31*4(3) + blr +FUNC_END(store_fpr_single_precision) diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore new file mode 100644 index 0000000..6e06004 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -0,0 +1 @@ +ptrace-gpr \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile new file mode 100644 index 0000000..1103772 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -0,0 +1,12 @@ +TEST_PROGS := ptrace-gpr + +include ../../lib.mk + +all: $(TEST_PROGS) + +CFLAGS += -m64 -I../../../../../usr/include + +$(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h + +clean: + rm -f $(TEST_PROGS) *.o diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c new file mode 100644 index 0000000..0b4ebcc --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.c @@ -0,0 +1,123 @@ +/* + * Ptrace test for GPR/FPR registers + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "ptrace-gpr.h" +#include "reg.h" + +/* Tracer and Tracee Shared Data */ +int shm_id; +int *cptr, *pptr; + +float a = FPR_1; +float b = FPR_2; +float c = FPR_3; + +void gpr(void) +{ + unsigned long gpr_buf[18]; + float fpr_buf[32]; + + cptr = (int *)shmat(shm_id, NULL, 0); + + asm __volatile__( + ASM_LOAD_GPR_IMMED(gpr_1) + ASM_LOAD_FPR_SINGLE_PRECISION(flt_1) + : + : [gpr_1]"i"(GPR_1), [flt_1] "r" (&a) + : "memory", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", + "r18", "r19", "r20", "r21", "r22", "r23", "r24", + "r25", "r26", "r27", "r28", "r29", "r30", "r31" + ); + + cptr[1] = 1; + + while (!cptr[0]) + asm volatile("" : : : "memory"); + + shmdt((void *)cptr); + store_gpr(gpr_buf); + store_fpr_single_precision(fpr_buf); + + if (validate_gpr(gpr_buf, GPR_3)) + exit(1); + + if (validate_fpr_float(fpr_buf, c)) + exit(1); + + exit(0); +} + +int trace_gpr(pid_t child) +{ + unsigned long gpr[18]; + unsigned long fpr[32]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_gpr(child, gpr)); + FAIL_IF(validate_gpr(gpr, GPR_1)); + FAIL_IF(show_fpr(child, fpr)); + FAIL_IF(validate_fpr(fpr, FPR_1_REP)); + FAIL_IF(write_gpr(child, GPR_3)); + FAIL_IF(write_fpr(child, FPR_3_REP)); + FAIL_IF(stop_trace(child)); + + return TEST_PASS; +} + +int ptrace_gpr(void) +{ + pid_t pid; + int ret, status; + + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + if (pid == 0) + gpr(); + + if (pid) { + pptr = (int *)shmat(shm_id, NULL, 0); + while (!pptr[1]) + asm volatile("" : : : "memory"); + + ret = trace_gpr(pid); + if (ret) { + kill(pid, SIGTERM); + shmdt((void *)pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + pptr[0] = 1; + shmdt((void *)pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_gpr, "ptrace_gpr"); +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h new file mode 100644 index 0000000..e30fef6 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-gpr.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#define GPR_1 1 +#define GPR_2 2 +#define GPR_3 3 +#define GPR_4 4 + +#define FPR_1 0.001 +#define FPR_2 0.002 +#define FPR_3 0.003 +#define FPR_4 0.004 + +#define FPR_1_REP 0x3f50624de0000000 +#define FPR_2_REP 0x3f60624de0000000 +#define FPR_3_REP 0x3f689374c0000000 +#define FPR_4_REP 0x3f70624de0000000 + +/* Buffer must have 18 elements */ +int validate_gpr(unsigned long *gpr, unsigned long val) +{ + int i, found = 1; + + for (i = 0; i < 18; i++) { + if (gpr[i] != val) { + printf("GPR[%d]: %lx Expected: %lx\n", + i+14, gpr[i], val); + found = 0; + } + } + + if (!found) + return TEST_FAIL; + return TEST_PASS; +} + +/* Buffer must have 32 elements */ +int validate_fpr(unsigned long *fpr, unsigned long val) +{ + int i, found = 1; + + for (i = 0; i < 32; i++) { + if (fpr[i] != val) { + printf("FPR[%d]: %lx Expected: %lx\n", i, fpr[i], val); + found = 0; + } + } + + if (!found) + return TEST_FAIL; + return TEST_PASS; +} + +/* Buffer must have 32 elements */ +int validate_fpr_float(float *fpr, float val) +{ + int i, found = 1; + + for (i = 0; i < 32; i++) { + if (fpr[i] != val) { + printf("FPR[%d]: %f Expected: %f\n", i, fpr[i], val); + found = 0; + } + } + + if (!found) + return TEST_FAIL; + return TEST_PASS; +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h new file mode 100644 index 0000000..9ee89eb --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h @@ -0,0 +1,376 @@ +/* + * Ptrace interface test helper functions + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "reg.h" +#include "utils.h" + +#define TEST_PASS 0 +#define TEST_FAIL 1 + +struct fpr_regs { + unsigned long fpr[32]; + unsigned long fpscr; +}; + + +#ifndef NT_PPC_TAR +#define NT_PPC_TAR 0x103 +#define NT_PPC_PPR 0x104 +#define NT_PPC_DSCR 0x105 +#define NT_PPC_EBB 0x106 +#define NT_PPC_PMU 0x107 +#define NT_PPC_TM_CGPR 0x108 +#define NT_PPC_TM_CFPR 0x109 +#define NT_PPC_TM_CVMX 0x10a +#define NT_PPC_TM_CVSX 0x10b +#define NT_PPC_TM_SPR 0x10c +#define NT_PPC_TM_CTAR 0x10d +#define NT_PPC_TM_CPPR 0x10e +#define NT_PPC_TM_CDSCR 0x10f +#endif + +/* Basic ptrace operations */ +int start_trace(pid_t child) +{ + int ret; + + ret = ptrace(PTRACE_ATTACH, child, NULL, NULL); + if (ret) { + perror("ptrace(PTRACE_ATTACH) failed"); + return TEST_FAIL; + } + ret = waitpid(child, NULL, 0); + if (ret != child) { + perror("waitpid() failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int stop_trace(pid_t child) +{ + int ret; + + ret = ptrace(PTRACE_DETACH, child, NULL, NULL); + if (ret) { + perror("ptrace(PTRACE_DETACH) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int cont_trace(pid_t child) +{ + int ret; + + ret = ptrace(PTRACE_CONT, child, NULL, NULL); + if (ret) { + perror("ptrace(PTRACE_CONT) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +/* FPR */ +int show_fpr(pid_t child, unsigned long *fpr) +{ + struct fpr_regs *regs; + int ret, i; + + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); + ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + if (fpr) { + for (i = 0; i < 32; i++) + fpr[i] = regs->fpr[i]; + } + return TEST_PASS; +} + +int write_fpr(pid_t child, unsigned long val) +{ + struct fpr_regs *regs; + int ret, i; + + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); + ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + for (i = 0; i < 32; i++) + regs->fpr[i] = val; + + ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int show_ckpt_fpr(pid_t child, unsigned long *fpr) +{ + struct fpr_regs *regs; + struct iovec iov; + int ret, i; + + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); + iov.iov_base = regs; + iov.iov_len = sizeof(struct fpr_regs); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + if (fpr) { + for (i = 0; i < 32; i++) + fpr[i] = regs->fpr[i]; + } + + return TEST_PASS; +} + +int write_ckpt_fpr(pid_t child, unsigned long val) +{ + struct fpr_regs *regs; + struct iovec iov; + int ret, i; + + regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs)); + iov.iov_base = regs; + iov.iov_len = sizeof(struct fpr_regs); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + for (i = 0; i < 32; i++) + regs->fpr[i] = val; + + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +/* GPR */ +int show_gpr(pid_t child, unsigned long *gpr) +{ + struct pt_regs *regs; + int ret, i; + + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); + if (!regs) { + perror("malloc() failed"); + return TEST_FAIL; + } + + ret = ptrace(PTRACE_GETREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + if (gpr) { + for (i = 14; i < 32; i++) + gpr[i-14] = regs->gpr[i]; + } + + return TEST_PASS; +} + +int write_gpr(pid_t child, unsigned long val) +{ + struct pt_regs *regs; + int i, ret; + + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); + if (!regs) { + perror("malloc() failed"); + return TEST_FAIL; + } + + ret = ptrace(PTRACE_GETREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + for (i = 14; i < 32; i++) + regs->gpr[i] = val; + + ret = ptrace(PTRACE_SETREGS, child, NULL, regs); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int show_ckpt_gpr(pid_t child, unsigned long *gpr) +{ + struct pt_regs *regs; + struct iovec iov; + int ret, i; + + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); + if (!regs) { + perror("malloc() failed"); + return TEST_FAIL; + } + + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(struct pt_regs); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + if (gpr) { + for (i = 14; i < 32; i++) + gpr[i-14] = regs->gpr[i]; + } + + return TEST_PASS; +} + +int write_ckpt_gpr(pid_t child, unsigned long val) +{ + struct pt_regs *regs; + struct iovec iov; + int ret, i; + + regs = (struct pt_regs *) malloc(sizeof(struct pt_regs)); + if (!regs) { + perror("malloc() failed\n"); + return TEST_FAIL; + } + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(struct pt_regs); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + for (i = 14; i < 32; i++) + regs->gpr[i] = val; + + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +/* Analyse TEXASR after TM failure */ +inline unsigned long get_tfiar(void) +{ + unsigned long ret; + + asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR)); + return ret; +} + +void analyse_texasr(unsigned long texasr) +{ + printf("TEXASR: %16lx\t", texasr); + + if (texasr & TEXASR_FP) + printf("TEXASR_FP "); + + if (texasr & TEXASR_DA) + printf("TEXASR_DA "); + + if (texasr & TEXASR_NO) + printf("TEXASR_NO "); + + if (texasr & TEXASR_FO) + printf("TEXASR_FO "); + + if (texasr & TEXASR_SIC) + printf("TEXASR_SIC "); + + if (texasr & TEXASR_NTC) + printf("TEXASR_NTC "); + + if (texasr & TEXASR_TC) + printf("TEXASR_TC "); + + if (texasr & TEXASR_TIC) + printf("TEXASR_TIC "); + + if (texasr & TEXASR_IC) + printf("TEXASR_IC "); + + if (texasr & TEXASR_IFC) + printf("TEXASR_IFC "); + + if (texasr & TEXASR_ABT) + printf("TEXASR_ABT "); + + if (texasr & TEXASR_SPD) + printf("TEXASR_SPD "); + + if (texasr & TEXASR_HV) + printf("TEXASR_HV "); + + if (texasr & TEXASR_PR) + printf("TEXASR_PR "); + + if (texasr & TEXASR_FS) + printf("TEXASR_FS "); + + if (texasr & TEXASR_TE) + printf("TEXASR_TE "); + + if (texasr & TEXASR_ROT) + printf("TEXASR_ROT "); + + printf("TFIAR :%lx\n", get_tfiar()); +} + +void store_gpr(unsigned long *addr); +void store_fpr(float *addr); -- cgit v1.1 From 509fcfe57b09637a80fe0fcacd052e8f445a2274 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:54 +0800 Subject: selftests/powerpc: Add ptrace tests for GPR/FPR registers in TM This patch adds ptrace interface test for GPR/FPR registers inside TM context. This adds ptrace interface based helper functions related to checkpointed GPR/FPR access. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 3 +- tools/testing/selftests/powerpc/ptrace/Makefile | 4 +- .../selftests/powerpc/ptrace/ptrace-tm-gpr.c | 158 +++++++++++++++++++++ 3 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 6e06004..4756bcd 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -1 +1,2 @@ -ptrace-gpr \ No newline at end of file +ptrace-gpr +ptrace-tm-gpr \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 1103772..84f5de9 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,10 +1,10 @@ -TEST_PROGS := ptrace-gpr +TEST_PROGS := ptrace-gpr ptrace-tm-gpr include ../../lib.mk all: $(TEST_PROGS) -CFLAGS += -m64 -I../../../../../usr/include +CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c new file mode 100644 index 0000000..59206b9 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-gpr.c @@ -0,0 +1,158 @@ +/* + * Ptrace test for GPR/FPR registers in TM context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "ptrace-gpr.h" +#include "tm.h" + +/* Tracer and Tracee Shared Data */ +int shm_id; +unsigned long *cptr, *pptr; + +float a = FPR_1; +float b = FPR_2; +float c = FPR_3; + +void tm_gpr(void) +{ + unsigned long gpr_buf[18]; + unsigned long result, texasr; + float fpr_buf[32]; + + printf("Starting the child\n"); + cptr = (unsigned long *)shmat(shm_id, NULL, 0); + +trans: + cptr[1] = 0; + asm __volatile__( + ASM_LOAD_GPR_IMMED(gpr_1) + ASM_LOAD_FPR_SINGLE_PRECISION(flt_1) + "1: ;" + "tbegin.;" + "beq 2f;" + ASM_LOAD_GPR_IMMED(gpr_2) + ASM_LOAD_FPR_SINGLE_PRECISION(flt_2) + "tsuspend.;" + "li 7, 1;" + "stw 7, 0(%[cptr1]);" + "tresume.;" + "b .;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + /* Transaction abort handler */ + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + : [res] "=r" (result), [texasr] "=r" (texasr) + : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), + [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a), + [flt_2] "r" (&b), [cptr1] "r" (&cptr[1]) + : "memory", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", + "r17", "r18", "r19", "r20", "r21", "r22", + "r23", "r24", "r25", "r26", "r27", "r28", + "r29", "r30", "r31" + ); + + if (result) { + if (!cptr[0]) + goto trans; + + shmdt((void *)cptr); + store_gpr(gpr_buf); + store_fpr_single_precision(fpr_buf); + + if (validate_gpr(gpr_buf, GPR_3)) + exit(1); + + if (validate_fpr_float(fpr_buf, c)) + exit(1); + + exit(0); + } + shmdt((void *)cptr); + exit(1); +} + +int trace_tm_gpr(pid_t child) +{ + unsigned long gpr[18]; + unsigned long fpr[32]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_gpr(child, gpr)); + FAIL_IF(validate_gpr(gpr, GPR_2)); + FAIL_IF(show_fpr(child, fpr)); + FAIL_IF(validate_fpr(fpr, FPR_2_REP)); + FAIL_IF(show_ckpt_fpr(child, fpr)); + FAIL_IF(validate_fpr(fpr, FPR_1_REP)); + FAIL_IF(show_ckpt_gpr(child, gpr)); + FAIL_IF(validate_gpr(gpr, GPR_1)); + FAIL_IF(write_ckpt_gpr(child, GPR_3)); + FAIL_IF(write_ckpt_fpr(child, FPR_3_REP)); + + pptr[0] = 1; + FAIL_IF(stop_trace(child)); + + return TEST_PASS; +} + +int ptrace_tm_gpr(void) +{ + pid_t pid; + int ret, status; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + if (pid == 0) + tm_gpr(); + + if (pid) { + pptr = (unsigned long *)shmat(shm_id, NULL, 0); + + while (!pptr[1]) + asm volatile("" : : : "memory"); + ret = trace_tm_gpr(pid); + if (ret) { + kill(pid, SIGTERM); + return TEST_FAIL; + } + + shmdt((void *)pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_gpr, "ptrace_tm_gpr"); +} -- cgit v1.1 From c7096dc0ee02ee7fd885c8010aad2c7d73d8c640 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:55 +0800 Subject: selftests/powerpc: Add ptrace tests for GPR/FPR registers in suspended TM This patch adds ptrace interface test for GPR/FPR registers inside suspended TM context. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 3 +- tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c | 169 +++++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 4756bcd..e85470e 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -1,2 +1,3 @@ ptrace-gpr -ptrace-tm-gpr \ No newline at end of file +ptrace-tm-gpr +ptrace-tm-spd-gpr \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 84f5de9..d246e28 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,4 +1,4 @@ -TEST_PROGS := ptrace-gpr ptrace-tm-gpr +TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c new file mode 100644 index 0000000..327fa94 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c @@ -0,0 +1,169 @@ +/* + * Ptrace test for GPR/FPR registers in TM Suspend context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "ptrace-gpr.h" +#include "tm.h" + +/* Tracer and Tracee Shared Data */ +int shm_id; +int *cptr, *pptr; + +float a = FPR_1; +float b = FPR_2; +float c = FPR_3; +float d = FPR_4; + +__attribute__((used)) void wait_parent(void) +{ + cptr[2] = 1; + while (!cptr[1]) + asm volatile("" : : : "memory"); +} + +void tm_spd_gpr(void) +{ + unsigned long gpr_buf[18]; + unsigned long result, texasr; + float fpr_buf[32]; + + cptr = (int *)shmat(shm_id, NULL, 0); + +trans: + cptr[2] = 0; + asm __volatile__( + ASM_LOAD_GPR_IMMED(gpr_1) + ASM_LOAD_FPR_SINGLE_PRECISION(flt_1) + + "1: ;" + "tbegin.;" + "beq 2f;" + + ASM_LOAD_GPR_IMMED(gpr_2) + "tsuspend.;" + ASM_LOAD_GPR_IMMED(gpr_4) + ASM_LOAD_FPR_SINGLE_PRECISION(flt_4) + + "bl wait_parent;" + "tresume.;" + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + /* Transaction abort handler */ + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + : [res] "=r" (result), [texasr] "=r" (texasr) + : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4), + [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a), + [flt_2] "r" (&b), [flt_4] "r" (&d) + : "memory", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" + ); + + if (result) { + if (!cptr[0]) + goto trans; + + shmdt((void *)cptr); + store_gpr(gpr_buf); + store_fpr_single_precision(fpr_buf); + + if (validate_gpr(gpr_buf, GPR_3)) + exit(1); + + if (validate_fpr_float(fpr_buf, c)) + exit(1); + exit(0); + } + shmdt((void *)cptr); + exit(1); +} + +int trace_tm_spd_gpr(pid_t child) +{ + unsigned long gpr[18]; + unsigned long fpr[32]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_gpr(child, gpr)); + FAIL_IF(validate_gpr(gpr, GPR_4)); + FAIL_IF(show_fpr(child, fpr)); + FAIL_IF(validate_fpr(fpr, FPR_4_REP)); + FAIL_IF(show_ckpt_fpr(child, fpr)); + FAIL_IF(validate_fpr(fpr, FPR_1_REP)); + FAIL_IF(show_ckpt_gpr(child, gpr)); + FAIL_IF(validate_gpr(gpr, GPR_1)); + FAIL_IF(write_ckpt_gpr(child, GPR_3)); + FAIL_IF(write_ckpt_fpr(child, FPR_3_REP)); + + pptr[0] = 1; + pptr[1] = 1; + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int ptrace_tm_spd_gpr(void) +{ + pid_t pid; + int ret, status; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + tm_spd_gpr(); + + if (pid) { + pptr = (int *)shmat(shm_id, NULL, 0); + pptr[0] = 0; + pptr[1] = 0; + + while (!pptr[2]) + asm volatile("" : : : "memory"); + ret = trace_tm_spd_gpr(pid); + if (ret) { + kill(pid, SIGTERM); + shmdt((void *)pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + shmdt((void *)pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_spd_gpr, "ptrace_tm_spd_gpr"); +} -- cgit v1.1 From 254dae59af6791f02bad50c70a1e5a27cb9deb8c Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:56 +0800 Subject: selftests/powerpc: Add ptrace tests for TAR, PPR, DSCR registers This patch adds ptrace interface test for TAR, PPR, DSCR registers. This also adds ptrace interface based helper functions related to TAR, PPR, DSCR register access. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 3 +- tools/testing/selftests/powerpc/ptrace/Makefile | 3 +- .../testing/selftests/powerpc/ptrace/ptrace-tar.c | 135 +++++++++++++++ .../testing/selftests/powerpc/ptrace/ptrace-tar.h | 50 ++++++ tools/testing/selftests/powerpc/ptrace/ptrace.h | 181 +++++++++++++++++++++ 5 files changed, 370 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tar.c create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tar.h (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index e85470e..ce94313 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -1,3 +1,4 @@ ptrace-gpr ptrace-tm-gpr -ptrace-tm-spd-gpr \ No newline at end of file +ptrace-tm-spd-gpr +ptrace-tar \ No newline at end of file diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index d246e28..c1060ff 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,4 +1,5 @@ -TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr +TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ + ptrace-tar include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c new file mode 100644 index 0000000..f9b5069 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.c @@ -0,0 +1,135 @@ +/* + * Ptrace test for TAR, PPR, DSCR registers + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "ptrace-tar.h" + +/* Tracer and Tracee Shared Data */ +int shm_id; +int *cptr; +int *pptr; + +void tar(void) +{ + unsigned long reg[3]; + int ret; + + cptr = (int *)shmat(shm_id, NULL, 0); + printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", + user_write, TAR_1, PPR_1, DSCR_1); + + mtspr(SPRN_TAR, TAR_1); + mtspr(SPRN_PPR, PPR_1); + mtspr(SPRN_DSCR, DSCR_1); + + cptr[2] = 1; + + /* Wait on parent */ + while (!cptr[0]) + asm volatile("" : : : "memory"); + + reg[0] = mfspr(SPRN_TAR); + reg[1] = mfspr(SPRN_PPR); + reg[2] = mfspr(SPRN_DSCR); + + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + user_read, reg[0], reg[1], reg[2]); + + /* Unblock the parent now */ + cptr[1] = 1; + shmdt((int *)cptr); + + ret = validate_tar_registers(reg, TAR_2, PPR_2, DSCR_2); + if (ret) + exit(1); + exit(0); +} + +int trace_tar(pid_t child) +{ + unsigned long reg[3]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_tar_registers(child, reg)); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + ptrace_read_running, reg[0], reg[1], reg[2]); + + FAIL_IF(validate_tar_registers(reg, TAR_1, PPR_1, DSCR_1)); + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int trace_tar_write(pid_t child) +{ + FAIL_IF(start_trace(child)); + FAIL_IF(write_tar_registers(child, TAR_2, PPR_2, DSCR_2)); + printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", + ptrace_write_running, TAR_2, PPR_2, DSCR_2); + + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int ptrace_tar(void) +{ + pid_t pid; + int ret, status; + + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + tar(); + + if (pid) { + pptr = (int *)shmat(shm_id, NULL, 0); + pptr[0] = 0; + pptr[1] = 0; + + while (!pptr[2]) + asm volatile("" : : : "memory"); + ret = trace_tar(pid); + if (ret) + return ret; + + ret = trace_tar_write(pid); + if (ret) + return ret; + + /* Unblock the child now */ + pptr[0] = 1; + + /* Wait on child */ + while (!pptr[1]) + asm volatile("" : : : "memory"); + + shmdt((int *)pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_PASS; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tar, "ptrace_tar"); +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h new file mode 100644 index 0000000..aed0aac --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tar.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#define TAR_1 10 +#define TAR_2 20 +#define TAR_3 30 +#define TAR_4 40 +#define TAR_5 50 + +#define DSCR_1 100 +#define DSCR_2 200 +#define DSCR_3 300 +#define DSCR_4 400 +#define DSCR_5 500 + +#define PPR_1 0x4000000000000 /* or 31,31,31*/ +#define PPR_2 0x8000000000000 /* or 1,1,1 */ +#define PPR_3 0xc000000000000 /* or 6,6,6 */ +#define PPR_4 0x10000000000000 /* or 2,2,2 */ + +char *user_read = "[User Read (Running)]"; +char *user_write = "[User Write (Running)]"; +char *ptrace_read_running = "[Ptrace Read (Running)]"; +char *ptrace_write_running = "[Ptrace Write (Running)]"; +char *ptrace_read_ckpt = "[Ptrace Read (Checkpointed)]"; +char *ptrace_write_ckpt = "[Ptrace Write (Checkpointed)]"; + +int validate_tar_registers(unsigned long *reg, unsigned long tar, + unsigned long ppr, unsigned long dscr) +{ + int match = 1; + + if (reg[0] != tar) + match = 0; + + if (reg[1] != ppr) + match = 0; + + if (reg[2] != dscr) + match = 0; + + if (!match) + return TEST_FAIL; + return TEST_PASS; +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h index 9ee89eb..fee71b8 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace.h +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h @@ -97,6 +97,187 @@ int cont_trace(pid_t child) return TEST_PASS; } +/* TAR, PPR, DSCR */ +int show_tar_registers(pid_t child, unsigned long *out) +{ + struct iovec iov; + unsigned long *reg; + int ret; + + reg = malloc(sizeof(unsigned long)); + if (!reg) { + perror("malloc() failed"); + return TEST_FAIL; + } + iov.iov_base = (u64 *) reg; + iov.iov_len = sizeof(unsigned long); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[0] = *reg; + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[1] = *reg; + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[2] = *reg; + + free(reg); + return TEST_PASS; +fail: + free(reg); + return TEST_FAIL; +} + +int write_tar_registers(pid_t child, unsigned long tar, + unsigned long ppr, unsigned long dscr) +{ + struct iovec iov; + unsigned long *reg; + int ret; + + reg = malloc(sizeof(unsigned long)); + if (!reg) { + perror("malloc() failed"); + return TEST_FAIL; + } + + iov.iov_base = (u64 *) reg; + iov.iov_len = sizeof(unsigned long); + + *reg = tar; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov); + if (ret) { + perror("ptrace(PTRACE_SETREGSET) failed"); + goto fail; + } + + *reg = ppr; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov); + if (ret) { + perror("ptrace(PTRACE_SETREGSET) failed"); + goto fail; + } + + *reg = dscr; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov); + if (ret) { + perror("ptrace(PTRACE_SETREGSET) failed"); + goto fail; + } + + free(reg); + return TEST_PASS; +fail: + free(reg); + return TEST_FAIL; +} + +int show_tm_checkpointed_state(pid_t child, unsigned long *out) +{ + struct iovec iov; + unsigned long *reg; + int ret; + + reg = malloc(sizeof(unsigned long)); + if (!reg) { + perror("malloc() failed"); + return TEST_FAIL; + } + + iov.iov_base = (u64 *) reg; + iov.iov_len = sizeof(unsigned long); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[0] = *reg; + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[1] = *reg; + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + if (out) + out[2] = *reg; + + free(reg); + return TEST_PASS; + +fail: + free(reg); + return TEST_FAIL; +} + +int write_ckpt_tar_registers(pid_t child, unsigned long tar, + unsigned long ppr, unsigned long dscr) +{ + struct iovec iov; + unsigned long *reg; + int ret; + + reg = malloc(sizeof(unsigned long)); + if (!reg) { + perror("malloc() failed"); + return TEST_FAIL; + } + + iov.iov_base = (u64 *) reg; + iov.iov_len = sizeof(unsigned long); + + *reg = tar; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + + *reg = ppr; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + + *reg = dscr; + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + goto fail; + } + + free(reg); + return TEST_PASS; +fail: + free(reg); + return TEST_FAIL; +} + /* FPR */ int show_fpr(pid_t child, unsigned long *fpr) { -- cgit v1.1 From fcf73a6bd9cb2b09045307e3ae88448f18750987 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:57 +0800 Subject: selftests/powerpc: Add ptrace tests for TAR, PPR, DSCR in TM This patch adds ptrace interface test for TAR, PPR, DSCR registers inside TM context. This also adds ptrace interface based helper functions related to checkpointed TAR, PPR, DSCR register access. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 3 +- tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../selftests/powerpc/ptrace/ptrace-tm-tar.c | 160 +++++++++++++++++++++ 3 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index ce94313..556a6e1 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -1,4 +1,5 @@ ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr -ptrace-tar \ No newline at end of file +ptrace-tar +ptrace-tm-tar diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index c1060ff..befa2c5 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,5 +1,5 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ - ptrace-tar + ptrace-tar ptrace-tm-tar include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c new file mode 100644 index 0000000..48b462f --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-tar.c @@ -0,0 +1,160 @@ +/* + * Ptrace test for TAR, PPR, DSCR registers in the TM context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "tm.h" +#include "ptrace-tar.h" + +int shm_id; +unsigned long *cptr, *pptr; + + +void tm_tar(void) +{ + unsigned long result, texasr; + unsigned long regs[3]; + int ret; + + cptr = (unsigned long *)shmat(shm_id, NULL, 0); + +trans: + cptr[1] = 0; + asm __volatile__( + "li 4, %[tar_1];" + "mtspr %[sprn_tar], 4;" /* TAR_1 */ + "li 4, %[dscr_1];" + "mtspr %[sprn_dscr], 4;" /* DSCR_1 */ + "or 31,31,31;" /* PPR_1*/ + + "1: ;" + "tbegin.;" + "beq 2f;" + + "li 4, %[tar_2];" + "mtspr %[sprn_tar], 4;" /* TAR_2 */ + "li 4, %[dscr_2];" + "mtspr %[sprn_dscr], 4;" /* DSCR_2 */ + "or 1,1,1;" /* PPR_2 */ + "tsuspend.;" + "li 0, 1;" + "stw 0, 0(%[cptr1]);" + "tresume.;" + "b .;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + /* Transaction abort handler */ + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + + : [res] "=r" (result), [texasr] "=r" (texasr) + : [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR), + [sprn_ppr]"i"(SPRN_PPR), [sprn_texasr]"i"(SPRN_TEXASR), + [tar_1]"i"(TAR_1), [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), + [dscr_2]"i"(DSCR_2), [cptr1] "r" (&cptr[1]) + : "memory", "r0", "r1", "r3", "r4", "r5", "r6" + ); + + /* TM failed, analyse */ + if (result) { + if (!cptr[0]) + goto trans; + + regs[0] = mfspr(SPRN_TAR); + regs[1] = mfspr(SPRN_PPR); + regs[2] = mfspr(SPRN_DSCR); + + shmdt(&cptr); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + user_read, regs[0], regs[1], regs[2]); + + ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4); + if (ret) + exit(1); + exit(0); + } + shmdt(&cptr); + exit(1); +} + +int trace_tm_tar(pid_t child) +{ + unsigned long regs[3]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_tar_registers(child, regs)); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + ptrace_read_running, regs[0], regs[1], regs[2]); + + FAIL_IF(validate_tar_registers(regs, TAR_2, PPR_2, DSCR_2)); + FAIL_IF(show_tm_checkpointed_state(child, regs)); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + ptrace_read_ckpt, regs[0], regs[1], regs[2]); + + FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1)); + FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4)); + printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", + ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4); + + pptr[0] = 1; + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int ptrace_tm_tar(void) +{ + pid_t pid; + int ret, status; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); + pid = fork(); + if (pid == 0) + tm_tar(); + + pptr = (unsigned long *)shmat(shm_id, NULL, 0); + pptr[0] = 0; + + if (pid) { + while (!pptr[1]) + asm volatile("" : : : "memory"); + ret = trace_tm_tar(pid); + if (ret) { + kill(pid, SIGTERM); + shmdt(&pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + shmdt(&pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_tar, "ptrace_tm_tar"); +} -- cgit v1.1 From 01f7fdc7b90e5afc3fafa19da970ec30caa44f3d Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:58 +0800 Subject: selftests/powerpc: Add ptrace tests for TAR, PPR, DSCR in suspended TM This patch adds ptrace interface test for TAR, PPR, DSCR registers inside suspended TM context. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../selftests/powerpc/ptrace/ptrace-tm-spd-tar.c | 174 +++++++++++++++++++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 556a6e1..7b3383a 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -3,3 +3,4 @@ ptrace-tm-gpr ptrace-tm-spd-gpr ptrace-tar ptrace-tm-tar +ptrace-tm-spd-tar diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index befa2c5..66accb2 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,5 +1,5 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ - ptrace-tar ptrace-tm-tar + ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c new file mode 100644 index 0000000..b3c061d --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c @@ -0,0 +1,174 @@ +/* + * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "tm.h" +#include "ptrace-tar.h" + +int shm_id; +int *cptr, *pptr; + +__attribute__((used)) void wait_parent(void) +{ + cptr[2] = 1; + while (!cptr[1]) + asm volatile("" : : : "memory"); +} + +void tm_spd_tar(void) +{ + unsigned long result, texasr; + unsigned long regs[3]; + int ret; + + cptr = (int *)shmat(shm_id, NULL, 0); + +trans: + cptr[2] = 0; + asm __volatile__( + "li 4, %[tar_1];" + "mtspr %[sprn_tar], 4;" /* TAR_1 */ + "li 4, %[dscr_1];" + "mtspr %[sprn_dscr], 4;" /* DSCR_1 */ + "or 31,31,31;" /* PPR_1*/ + + "1: ;" + "tbegin.;" + "beq 2f;" + + "li 4, %[tar_2];" + "mtspr %[sprn_tar], 4;" /* TAR_2 */ + "li 4, %[dscr_2];" + "mtspr %[sprn_dscr], 4;" /* DSCR_2 */ + "or 1,1,1;" /* PPR_2 */ + + "tsuspend.;" + "li 4, %[tar_3];" + "mtspr %[sprn_tar], 4;" /* TAR_3 */ + "li 4, %[dscr_3];" + "mtspr %[sprn_dscr], 4;" /* DSCR_3 */ + "or 6,6,6;" /* PPR_3 */ + "bl wait_parent;" + "tresume.;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + /* Transaction abort handler */ + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + + : [res] "=r" (result), [texasr] "=r" (texasr) + : [val] "r" (cptr[1]), [sprn_dscr]"i"(SPRN_DSCR), + [sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR), + [sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1), + [dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2), + [tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3) + : "memory", "r0", "r1", "r3", "r4", "r5", "r6" + ); + + /* TM failed, analyse */ + if (result) { + if (!cptr[0]) + goto trans; + + regs[0] = mfspr(SPRN_TAR); + regs[1] = mfspr(SPRN_PPR); + regs[2] = mfspr(SPRN_DSCR); + + shmdt(&cptr); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + user_read, regs[0], regs[1], regs[2]); + + ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4); + if (ret) + exit(1); + exit(0); + } + shmdt(&cptr); + exit(1); +} + +int trace_tm_spd_tar(pid_t child) +{ + unsigned long regs[3]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_tar_registers(child, regs)); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + ptrace_read_running, regs[0], regs[1], regs[2]); + + FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3)); + FAIL_IF(show_tm_checkpointed_state(child, regs)); + printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n", + ptrace_read_ckpt, regs[0], regs[1], regs[2]); + + FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1)); + FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4)); + printf("%-30s TAR: %u PPR: %lx DSCR: %u\n", + ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4); + + pptr[0] = 1; + pptr[1] = 1; + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int ptrace_tm_spd_tar(void) +{ + pid_t pid; + int ret, status; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); + pid = fork(); + if (pid == 0) + tm_spd_tar(); + + pptr = (int *)shmat(shm_id, NULL, 0); + pptr[0] = 0; + pptr[1] = 0; + + if (pid) { + while (!pptr[2]) + asm volatile("" : : : "memory"); + ret = trace_tm_spd_tar(pid); + if (ret) { + kill(pid, SIGTERM); + shmdt(&pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + shmdt(&pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar"); +} -- cgit v1.1 From 0da535c0844b81111f837670e0b9b300cc75b100 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:32:59 +0800 Subject: selftests/powerpc: Add ptrace tests for VSX, VMX registers This patch adds ptrace interface test for VSX, VMX registers. This also adds ptrace interface based helper functions related to VSX, VMX registers access. This also adds some assembly helper functions related to VSX and VMX registers. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/lib/reg.S | 265 +++++++++++++++++++++ tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../testing/selftests/powerpc/ptrace/ptrace-vsx.c | 117 +++++++++ .../testing/selftests/powerpc/ptrace/ptrace-vsx.h | 127 ++++++++++ tools/testing/selftests/powerpc/ptrace/ptrace.h | 119 +++++++++ 6 files changed, 630 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/lib/reg.S b/tools/testing/selftests/powerpc/lib/reg.S index b6aee2f..0dc44f0d 100644 --- a/tools/testing/selftests/powerpc/lib/reg.S +++ b/tools/testing/selftests/powerpc/lib/reg.S @@ -130,3 +130,268 @@ FUNC_START(store_fpr_single_precision) stfs 31, 31*4(3) blr FUNC_END(store_fpr_single_precision) + +/* VMX/VSX registers - unsigned long buf[128] */ +FUNC_START(loadvsx) + lis 4, 0 + LXVD2X (0,(4),(3)) + addi 4, 4, 16 + LXVD2X (1,(4),(3)) + addi 4, 4, 16 + LXVD2X (2,(4),(3)) + addi 4, 4, 16 + LXVD2X (3,(4),(3)) + addi 4, 4, 16 + LXVD2X (4,(4),(3)) + addi 4, 4, 16 + LXVD2X (5,(4),(3)) + addi 4, 4, 16 + LXVD2X (6,(4),(3)) + addi 4, 4, 16 + LXVD2X (7,(4),(3)) + addi 4, 4, 16 + LXVD2X (8,(4),(3)) + addi 4, 4, 16 + LXVD2X (9,(4),(3)) + addi 4, 4, 16 + LXVD2X (10,(4),(3)) + addi 4, 4, 16 + LXVD2X (11,(4),(3)) + addi 4, 4, 16 + LXVD2X (12,(4),(3)) + addi 4, 4, 16 + LXVD2X (13,(4),(3)) + addi 4, 4, 16 + LXVD2X (14,(4),(3)) + addi 4, 4, 16 + LXVD2X (15,(4),(3)) + addi 4, 4, 16 + LXVD2X (16,(4),(3)) + addi 4, 4, 16 + LXVD2X (17,(4),(3)) + addi 4, 4, 16 + LXVD2X (18,(4),(3)) + addi 4, 4, 16 + LXVD2X (19,(4),(3)) + addi 4, 4, 16 + LXVD2X (20,(4),(3)) + addi 4, 4, 16 + LXVD2X (21,(4),(3)) + addi 4, 4, 16 + LXVD2X (22,(4),(3)) + addi 4, 4, 16 + LXVD2X (23,(4),(3)) + addi 4, 4, 16 + LXVD2X (24,(4),(3)) + addi 4, 4, 16 + LXVD2X (25,(4),(3)) + addi 4, 4, 16 + LXVD2X (26,(4),(3)) + addi 4, 4, 16 + LXVD2X (27,(4),(3)) + addi 4, 4, 16 + LXVD2X (28,(4),(3)) + addi 4, 4, 16 + LXVD2X (29,(4),(3)) + addi 4, 4, 16 + LXVD2X (30,(4),(3)) + addi 4, 4, 16 + LXVD2X (31,(4),(3)) + addi 4, 4, 16 + LXVD2X (32,(4),(3)) + addi 4, 4, 16 + LXVD2X (33,(4),(3)) + addi 4, 4, 16 + LXVD2X (34,(4),(3)) + addi 4, 4, 16 + LXVD2X (35,(4),(3)) + addi 4, 4, 16 + LXVD2X (36,(4),(3)) + addi 4, 4, 16 + LXVD2X (37,(4),(3)) + addi 4, 4, 16 + LXVD2X (38,(4),(3)) + addi 4, 4, 16 + LXVD2X (39,(4),(3)) + addi 4, 4, 16 + LXVD2X (40,(4),(3)) + addi 4, 4, 16 + LXVD2X (41,(4),(3)) + addi 4, 4, 16 + LXVD2X (42,(4),(3)) + addi 4, 4, 16 + LXVD2X (43,(4),(3)) + addi 4, 4, 16 + LXVD2X (44,(4),(3)) + addi 4, 4, 16 + LXVD2X (45,(4),(3)) + addi 4, 4, 16 + LXVD2X (46,(4),(3)) + addi 4, 4, 16 + LXVD2X (47,(4),(3)) + addi 4, 4, 16 + LXVD2X (48,(4),(3)) + addi 4, 4, 16 + LXVD2X (49,(4),(3)) + addi 4, 4, 16 + LXVD2X (50,(4),(3)) + addi 4, 4, 16 + LXVD2X (51,(4),(3)) + addi 4, 4, 16 + LXVD2X (52,(4),(3)) + addi 4, 4, 16 + LXVD2X (53,(4),(3)) + addi 4, 4, 16 + LXVD2X (54,(4),(3)) + addi 4, 4, 16 + LXVD2X (55,(4),(3)) + addi 4, 4, 16 + LXVD2X (56,(4),(3)) + addi 4, 4, 16 + LXVD2X (57,(4),(3)) + addi 4, 4, 16 + LXVD2X (58,(4),(3)) + addi 4, 4, 16 + LXVD2X (59,(4),(3)) + addi 4, 4, 16 + LXVD2X (60,(4),(3)) + addi 4, 4, 16 + LXVD2X (61,(4),(3)) + addi 4, 4, 16 + LXVD2X (62,(4),(3)) + addi 4, 4, 16 + LXVD2X (63,(4),(3)) + blr +FUNC_END(loadvsx) + +FUNC_START(storevsx) + lis 4, 0 + STXVD2X (0,(4),(3)) + addi 4, 4, 16 + STXVD2X (1,(4),(3)) + addi 4, 4, 16 + STXVD2X (2,(4),(3)) + addi 4, 4, 16 + STXVD2X (3,(4),(3)) + addi 4, 4, 16 + STXVD2X (4,(4),(3)) + addi 4, 4, 16 + STXVD2X (5,(4),(3)) + addi 4, 4, 16 + STXVD2X (6,(4),(3)) + addi 4, 4, 16 + STXVD2X (7,(4),(3)) + addi 4, 4, 16 + STXVD2X (8,(4),(3)) + addi 4, 4, 16 + STXVD2X (9,(4),(3)) + addi 4, 4, 16 + STXVD2X (10,(4),(3)) + addi 4, 4, 16 + STXVD2X (11,(4),(3)) + addi 4, 4, 16 + STXVD2X (12,(4),(3)) + addi 4, 4, 16 + STXVD2X (13,(4),(3)) + addi 4, 4, 16 + STXVD2X (14,(4),(3)) + addi 4, 4, 16 + STXVD2X (15,(4),(3)) + addi 4, 4, 16 + STXVD2X (16,(4),(3)) + addi 4, 4, 16 + STXVD2X (17,(4),(3)) + addi 4, 4, 16 + STXVD2X (18,(4),(3)) + addi 4, 4, 16 + STXVD2X (19,(4),(3)) + addi 4, 4, 16 + STXVD2X (20,(4),(3)) + addi 4, 4, 16 + STXVD2X (21,(4),(3)) + addi 4, 4, 16 + STXVD2X (22,(4),(3)) + addi 4, 4, 16 + STXVD2X (23,(4),(3)) + addi 4, 4, 16 + STXVD2X (24,(4),(3)) + addi 4, 4, 16 + STXVD2X (25,(4),(3)) + addi 4, 4, 16 + STXVD2X (26,(4),(3)) + addi 4, 4, 16 + STXVD2X (27,(4),(3)) + addi 4, 4, 16 + STXVD2X (28,(4),(3)) + addi 4, 4, 16 + STXVD2X (29,(4),(3)) + addi 4, 4, 16 + STXVD2X (30,(4),(3)) + addi 4, 4, 16 + STXVD2X (31,(4),(3)) + addi 4, 4, 16 + STXVD2X (32,(4),(3)) + addi 4, 4, 16 + STXVD2X (33,(4),(3)) + addi 4, 4, 16 + STXVD2X (34,(4),(3)) + addi 4, 4, 16 + STXVD2X (35,(4),(3)) + addi 4, 4, 16 + STXVD2X (36,(4),(3)) + addi 4, 4, 16 + STXVD2X (37,(4),(3)) + addi 4, 4, 16 + STXVD2X (38,(4),(3)) + addi 4, 4, 16 + STXVD2X (39,(4),(3)) + addi 4, 4, 16 + STXVD2X (40,(4),(3)) + addi 4, 4, 16 + STXVD2X (41,(4),(3)) + addi 4, 4, 16 + STXVD2X (42,(4),(3)) + addi 4, 4, 16 + STXVD2X (43,(4),(3)) + addi 4, 4, 16 + STXVD2X (44,(4),(3)) + addi 4, 4, 16 + STXVD2X (45,(4),(3)) + addi 4, 4, 16 + STXVD2X (46,(4),(3)) + addi 4, 4, 16 + STXVD2X (47,(4),(3)) + addi 4, 4, 16 + STXVD2X (48,(4),(3)) + addi 4, 4, 16 + STXVD2X (49,(4),(3)) + addi 4, 4, 16 + STXVD2X (50,(4),(3)) + addi 4, 4, 16 + STXVD2X (51,(4),(3)) + addi 4, 4, 16 + STXVD2X (52,(4),(3)) + addi 4, 4, 16 + STXVD2X (53,(4),(3)) + addi 4, 4, 16 + STXVD2X (54,(4),(3)) + addi 4, 4, 16 + STXVD2X (55,(4),(3)) + addi 4, 4, 16 + STXVD2X (56,(4),(3)) + addi 4, 4, 16 + STXVD2X (57,(4),(3)) + addi 4, 4, 16 + STXVD2X (58,(4),(3)) + addi 4, 4, 16 + STXVD2X (59,(4),(3)) + addi 4, 4, 16 + STXVD2X (60,(4),(3)) + addi 4, 4, 16 + STXVD2X (61,(4),(3)) + addi 4, 4, 16 + STXVD2X (62,(4),(3)) + addi 4, 4, 16 + STXVD2X (63,(4),(3)) + blr +FUNC_END(storevsx) diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 7b3383a..720c002 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -4,3 +4,4 @@ ptrace-tm-spd-gpr ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar +ptrace-vsx diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 66accb2..18790ff 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,5 +1,5 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ - ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar + ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c new file mode 100644 index 0000000..04084ee --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.c @@ -0,0 +1,117 @@ +/* + * Ptrace test for VMX/VSX registers + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "ptrace-vsx.h" + +/* Tracer and Tracee Shared Data */ +int shm_id; +int *cptr, *pptr; + +unsigned long fp_load[VEC_MAX]; +unsigned long fp_load_new[VEC_MAX]; +unsigned long fp_store[VEC_MAX]; + +void vsx(void) +{ + int ret; + + cptr = (int *)shmat(shm_id, NULL, 0); + loadvsx(fp_load, 0); + cptr[1] = 1; + + while (!cptr[0]) + asm volatile("" : : : "memory"); + shmdt((void *) cptr); + + storevsx(fp_store, 0); + ret = compare_vsx_vmx(fp_store, fp_load_new); + if (ret) + exit(1); + exit(0); +} + +int trace_vsx(pid_t child) +{ + unsigned long vsx[VSX_MAX]; + unsigned long vmx[VMX_MAX + 2][2]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_vsx(child, vsx)); + FAIL_IF(validate_vsx(vsx, fp_load)); + FAIL_IF(show_vmx(child, vmx)); + FAIL_IF(validate_vmx(vmx, fp_load)); + + memset(vsx, 0, sizeof(vsx)); + memset(vmx, 0, sizeof(vmx)); + load_vsx_vmx(fp_load_new, vsx, vmx); + + FAIL_IF(write_vsx(child, vsx)); + FAIL_IF(write_vmx(child, vmx)); + FAIL_IF(stop_trace(child)); + + return TEST_PASS; +} + +int ptrace_vsx(void) +{ + pid_t pid; + int ret, status, i; + + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); + + for (i = 0; i < VEC_MAX; i++) + fp_load[i] = i + rand(); + + for (i = 0; i < VEC_MAX; i++) + fp_load_new[i] = i + 2 * rand(); + + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + vsx(); + + if (pid) { + pptr = (int *)shmat(shm_id, NULL, 0); + while (!pptr[1]) + asm volatile("" : : : "memory"); + + ret = trace_vsx(pid); + if (ret) { + kill(pid, SIGTERM); + shmdt((void *)pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + pptr[0] = 1; + shmdt((void *)pptr); + + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_vsx, "ptrace_vsx"); +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h new file mode 100644 index 0000000..f4e4b42 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-vsx.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#define VEC_MAX 128 +#define VSX_MAX 32 +#define VMX_MAX 32 + +/* + * unsigned long vsx[32] + * unsigned long load[128] + */ +int validate_vsx(unsigned long *vsx, unsigned long *load) +{ + int i; + + for (i = 0; i < VSX_MAX; i++) { + if (vsx[i] != load[2 * i + 1]) { + printf("vsx[%d]: %lx load[%d] %lx\n", + i, vsx[i], 2 * i + 1, load[2 * i + 1]); + return TEST_FAIL; + } + } + return TEST_PASS; +} + +/* + * unsigned long vmx[32][2] + * unsigned long load[128] + */ +int validate_vmx(unsigned long vmx[][2], unsigned long *load) +{ + int i; + + for (i = 0; i < VMX_MAX; i++) { + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if ((vmx[i][0] != load[64 + 2 * i]) || + (vmx[i][1] != load[65 + 2 * i])) { + printf("vmx[%d][0]: %lx load[%d] %lx\n", + i, vmx[i][0], 64 + 2 * i, + load[64 + 2 * i]); + printf("vmx[%d][1]: %lx load[%d] %lx\n", + i, vmx[i][1], 65 + 2 * i, + load[65 + 2 * i]); + return TEST_FAIL; + } + #else /* + * In LE each value pair is stored in an + * alternate manner. + */ + if ((vmx[i][0] != load[65 + 2 * i]) || + (vmx[i][1] != load[64 + 2 * i])) { + printf("vmx[%d][0]: %lx load[%d] %lx\n", + i, vmx[i][0], 65 + 2 * i, + load[65 + 2 * i]); + printf("vmx[%d][1]: %lx load[%d] %lx\n", + i, vmx[i][1], 64 + 2 * i, + load[64 + 2 * i]); + return TEST_FAIL; + } + #endif + } + return TEST_PASS; +} + +/* + * unsigned long store[128] + * unsigned long load[128] + */ +int compare_vsx_vmx(unsigned long *store, unsigned long *load) +{ + int i; + + for (i = 0; i < VSX_MAX; i++) { + if (store[1 + 2 * i] != load[1 + 2 * i]) { + printf("store[%d]: %lx load[%d] %lx\n", + 1 + 2 * i, store[i], + 1 + 2 * i, load[i]); + return TEST_FAIL; + } + } + + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + for (i = 64; i < VEC_MAX; i++) { + if (store[i] != load[i]) { + printf("store[%d]: %lx load[%d] %lx\n", + i, store[i], i, load[i]); + return TEST_FAIL; + } + } + #else /* In LE each value pair is stored in an alternate manner */ + for (i = 64; i < VEC_MAX; i++) { + if (!(i % 2) && (store[i] != load[i+1])) { + printf("store[%d]: %lx load[%d] %lx\n", + i, store[i], i+1, load[i+1]); + return TEST_FAIL; + } + if ((i % 2) && (store[i] != load[i-1])) { + printf("here store[%d]: %lx load[%d] %lx\n", + i, store[i], i-1, load[i-1]); + return TEST_FAIL; + } + } + #endif + return TEST_PASS; +} + +void load_vsx_vmx(unsigned long *load, unsigned long *vsx, + unsigned long vmx[][2]) +{ + int i; + + for (i = 0; i < VSX_MAX; i++) + vsx[i] = load[1 + 2 * i]; + + for (i = 0; i < VMX_MAX; i++) { + vmx[i][0] = load[64 + 2 * i]; + vmx[i][1] = load[65 + 2 * i]; + } +} + +void loadvsx(void *p, int tmp); +void storevsx(void *p, int tmp); diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h index fee71b8..9aa0498 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace.h +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h @@ -486,6 +486,125 @@ int write_ckpt_gpr(pid_t child, unsigned long val) return TEST_PASS; } +/* VMX */ +int show_vmx(pid_t child, unsigned long vmx[][2]) +{ + int ret; + + ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx); + if (ret) { + perror("ptrace(PTRACE_GETVRREGS) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int show_vmx_ckpt(pid_t child, unsigned long vmx[][2]) +{ + unsigned long regs[34][2]; + struct iovec iov; + int ret; + + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(regs); + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed"); + return TEST_FAIL; + } + memcpy(vmx, regs, sizeof(regs)); + return TEST_PASS; +} + + +int write_vmx(pid_t child, unsigned long vmx[][2]) +{ + int ret; + + ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx); + if (ret) { + perror("ptrace(PTRACE_SETVRREGS) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int write_vmx_ckpt(pid_t child, unsigned long vmx[][2]) +{ + unsigned long regs[34][2]; + struct iovec iov; + int ret; + + memcpy(regs, vmx, sizeof(regs)); + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(regs); + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov); + if (ret) { + perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +/* VSX */ +int show_vsx(pid_t child, unsigned long *vsx) +{ + int ret; + + ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx); + if (ret) { + perror("ptrace(PTRACE_GETVSRREGS) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int show_vsx_ckpt(pid_t child, unsigned long *vsx) +{ + unsigned long regs[32]; + struct iovec iov; + int ret; + + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(regs); + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed"); + return TEST_FAIL; + } + memcpy(vsx, regs, sizeof(regs)); + return TEST_PASS; +} + +int write_vsx(pid_t child, unsigned long *vsx) +{ + int ret; + + ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx); + if (ret) { + perror("ptrace(PTRACE_SETVSRREGS) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + +int write_vsx_ckpt(pid_t child, unsigned long *vsx) +{ + unsigned long regs[32]; + struct iovec iov; + int ret; + + memcpy(regs, vsx, sizeof(regs)); + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(regs); + ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov); + if (ret) { + perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed"); + return TEST_FAIL; + } + return TEST_PASS; +} + /* Analyse TEXASR after TM failure */ inline unsigned long get_tfiar(void) { -- cgit v1.1 From 11508074c9a74a00df1aa6cfba81d1fdabdaa51c Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:33:00 +0800 Subject: selftests/powerpc: Add ptrace tests for VSX, VMX registers in TM This patch adds ptrace interface test for VSX, VMX registers inside TM context. This also adds ptrace interface based helper functions related to chckpointed VSX, VMX registers access. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../selftests/powerpc/ptrace/ptrace-tm-vsx.c | 168 +++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 720c002..f1f3055 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -5,3 +5,4 @@ ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx +ptrace-tm-vsx diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 18790ff..f82cfe1 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,5 +1,5 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ - ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx + ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c new file mode 100644 index 0000000..b4081e2 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c @@ -0,0 +1,168 @@ +/* + * Ptrace test for VMX/VSX registers in the TM context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "tm.h" +#include "ptrace-vsx.h" + +int shm_id; +unsigned long *cptr, *pptr; + +unsigned long fp_load[VEC_MAX]; +unsigned long fp_store[VEC_MAX]; +unsigned long fp_load_ckpt[VEC_MAX]; +unsigned long fp_load_ckpt_new[VEC_MAX]; + +__attribute__((used)) void load_vsx(void) +{ + loadvsx(fp_load, 0); +} + +__attribute__((used)) void load_vsx_ckpt(void) +{ + loadvsx(fp_load_ckpt, 0); +} + +void tm_vsx(void) +{ + unsigned long result, texasr; + int ret; + + cptr = (unsigned long *)shmat(shm_id, NULL, 0); + +trans: + cptr[1] = 0; + asm __volatile__( + "bl load_vsx_ckpt;" + + "1: ;" + "tbegin.;" + "beq 2f;" + + "bl load_vsx;" + "tsuspend.;" + "li 7, 1;" + "stw 7, 0(%[cptr1]);" + "tresume.;" + "b .;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + : [res] "=r" (result), [texasr] "=r" (texasr) + : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt), + [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "r" (&cptr[1]) + : "memory", "r0", "r1", "r2", "r3", "r4", + "r7", "r8", "r9", "r10", "r11" + ); + + if (result) { + if (!cptr[0]) + goto trans; + + shmdt((void *)cptr); + storevsx(fp_store, 0); + ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new); + if (ret) + exit(1); + exit(0); + } + shmdt((void *)cptr); + exit(1); +} + +int trace_tm_vsx(pid_t child) +{ + unsigned long vsx[VSX_MAX]; + unsigned long vmx[VMX_MAX + 2][2]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_vsx(child, vsx)); + FAIL_IF(validate_vsx(vsx, fp_load)); + FAIL_IF(show_vmx(child, vmx)); + FAIL_IF(validate_vmx(vmx, fp_load)); + FAIL_IF(show_vsx_ckpt(child, vsx)); + FAIL_IF(validate_vsx(vsx, fp_load_ckpt)); + FAIL_IF(show_vmx_ckpt(child, vmx)); + FAIL_IF(validate_vmx(vmx, fp_load_ckpt)); + memset(vsx, 0, sizeof(vsx)); + memset(vmx, 0, sizeof(vmx)); + + load_vsx_vmx(fp_load_ckpt_new, vsx, vmx); + + FAIL_IF(write_vsx_ckpt(child, vsx)); + FAIL_IF(write_vmx_ckpt(child, vmx)); + pptr[0] = 1; + FAIL_IF(stop_trace(child)); + return TEST_PASS; +} + +int ptrace_tm_vsx(void) +{ + pid_t pid; + int ret, status, i; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT); + + for (i = 0; i < 128; i++) { + fp_load[i] = 1 + rand(); + fp_load_ckpt[i] = 1 + 2 * rand(); + fp_load_ckpt_new[i] = 1 + 3 * rand(); + } + + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + tm_vsx(); + + if (pid) { + pptr = (unsigned long *)shmat(shm_id, NULL, 0); + while (!pptr[1]) + asm volatile("" : : : "memory"); + + ret = trace_tm_vsx(pid); + if (ret) { + kill(pid, SIGKILL); + shmdt((void *)pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + shmdt((void *)pptr); + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx"); +} -- cgit v1.1 From a18b55bf51b32136fb9c5190b1cbf86c75117ead Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:33:01 +0800 Subject: selftests/powerpc: Add ptrace tests for VSX, VMX registers in suspended TM This patch adds ptrace interface test for VSX, VMX registers inside suspended TM context. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 3 +- .../selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c | 185 +++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index f1f3055..4943953 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -6,3 +6,4 @@ ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx +ptrace-tm-spd-vsx diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index f82cfe1..f3f4129 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,5 +1,6 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ - ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx + ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ + ptrace-tm-spd-vsx include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c new file mode 100644 index 0000000..0df3c23 --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-vsx.c @@ -0,0 +1,185 @@ +/* + * Ptrace test for VMX/VSX registers in the TM Suspend context + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "tm.h" +#include "ptrace-vsx.h" + +int shm_id; +int *cptr, *pptr; + +unsigned long fp_load[VEC_MAX]; +unsigned long fp_load_new[VEC_MAX]; +unsigned long fp_store[VEC_MAX]; +unsigned long fp_load_ckpt[VEC_MAX]; +unsigned long fp_load_ckpt_new[VEC_MAX]; + +__attribute__((used)) void load_vsx(void) +{ + loadvsx(fp_load, 0); +} + +__attribute__((used)) void load_vsx_new(void) +{ + loadvsx(fp_load_new, 0); +} + +__attribute__((used)) void load_vsx_ckpt(void) +{ + loadvsx(fp_load_ckpt, 0); +} + +__attribute__((used)) void wait_parent(void) +{ + cptr[2] = 1; + while (!cptr[1]) + asm volatile("" : : : "memory"); +} + +void tm_spd_vsx(void) +{ + unsigned long result, texasr; + int ret; + + cptr = (int *)shmat(shm_id, NULL, 0); + +trans: + cptr[2] = 0; + asm __volatile__( + "bl load_vsx_ckpt;" + + "1: ;" + "tbegin.;" + "beq 2f;" + + "bl load_vsx_new;" + "tsuspend.;" + "bl load_vsx;" + "bl wait_parent;" + "tresume.;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + "2: ;" + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + : [res] "=r" (result), [texasr] "=r" (texasr) + : [fp_load] "r" (fp_load), [fp_load_ckpt] "r" (fp_load_ckpt), + [sprn_texasr] "i" (SPRN_TEXASR) + : "memory", "r0", "r1", "r2", "r3", "r4", + "r8", "r9", "r10", "r11" + ); + + if (result) { + if (!cptr[0]) + goto trans; + shmdt((void *)cptr); + + storevsx(fp_store, 0); + ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new); + if (ret) + exit(1); + exit(0); + } + shmdt((void *)cptr); + exit(1); +} + +int trace_tm_spd_vsx(pid_t child) +{ + unsigned long vsx[VSX_MAX]; + unsigned long vmx[VMX_MAX + 2][2]; + + FAIL_IF(start_trace(child)); + FAIL_IF(show_vsx(child, vsx)); + FAIL_IF(validate_vsx(vsx, fp_load)); + FAIL_IF(show_vmx(child, vmx)); + FAIL_IF(validate_vmx(vmx, fp_load)); + FAIL_IF(show_vsx_ckpt(child, vsx)); + FAIL_IF(validate_vsx(vsx, fp_load_ckpt)); + FAIL_IF(show_vmx_ckpt(child, vmx)); + FAIL_IF(validate_vmx(vmx, fp_load_ckpt)); + + memset(vsx, 0, sizeof(vsx)); + memset(vmx, 0, sizeof(vmx)); + + load_vsx_vmx(fp_load_ckpt_new, vsx, vmx); + + FAIL_IF(write_vsx_ckpt(child, vsx)); + FAIL_IF(write_vmx_ckpt(child, vmx)); + + pptr[0] = 1; + pptr[1] = 1; + FAIL_IF(stop_trace(child)); + + return TEST_PASS; +} + +int ptrace_tm_spd_vsx(void) +{ + pid_t pid; + int ret, status, i; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT); + + for (i = 0; i < 128; i++) { + fp_load[i] = 1 + rand(); + fp_load_new[i] = 1 + 2 * rand(); + fp_load_ckpt[i] = 1 + 3 * rand(); + fp_load_ckpt_new[i] = 1 + 4 * rand(); + } + + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + tm_spd_vsx(); + + if (pid) { + pptr = (int *)shmat(shm_id, NULL, 0); + while (!pptr[2]) + asm volatile("" : : : "memory"); + + ret = trace_tm_spd_vsx(pid); + if (ret) { + kill(pid, SIGKILL); + shmdt((void *)pptr); + shmctl(shm_id, IPC_RMID, NULL); + return TEST_FAIL; + } + + shmdt((void *)pptr); + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_spd_vsx, "ptrace_tm_spd_vsx"); +} -- cgit v1.1 From 5bdac52f3c67e1262b1979081a362fdedebd2ed2 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 30 Sep 2016 10:33:02 +0800 Subject: selftests/powerpc: Add ptrace tests for TM SPR registers This patch adds ptrace interface test for TM SPR registers. This also adds ptrace interface based helper functions related to TM SPR registers access. Signed-off-by: Anshuman Khandual Signed-off-by: Simon Guo Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/ptrace/.gitignore | 1 + tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- .../selftests/powerpc/ptrace/ptrace-tm-spr.c | 168 +++++++++++++++++++++ tools/testing/selftests/powerpc/ptrace/ptrace.h | 35 +++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c (limited to 'tools') diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 4943953..349acfa 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore @@ -7,3 +7,4 @@ ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx ptrace-tm-spd-vsx +ptrace-tm-spr diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index f3f4129..fe6bc60 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,6 +1,6 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ - ptrace-tm-spd-vsx + ptrace-tm-spd-vsx ptrace-tm-spr include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c new file mode 100644 index 0000000..94e57cb --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c @@ -0,0 +1,168 @@ +/* + * Ptrace test TM SPR registers + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "ptrace.h" +#include "tm.h" + +/* Tracee and tracer shared data */ +struct shared { + int flag; + struct tm_spr_regs regs; +}; +unsigned long tfhar; + +int shm_id; +struct shared *cptr, *pptr; + +int shm_id1; +int *cptr1, *pptr1; + +#define TM_KVM_SCHED 0xe0000001ac000001 +int validate_tm_spr(struct tm_spr_regs *regs) +{ + FAIL_IF(regs->tm_tfhar != tfhar); + FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0)); + + return TEST_PASS; +} + +void tm_spr(void) +{ + unsigned long result, texasr; + int ret; + + cptr = (struct shared *)shmat(shm_id, NULL, 0); + cptr1 = (int *)shmat(shm_id1, NULL, 0); + +trans: + cptr1[0] = 0; + asm __volatile__( + "1: ;" + /* TM failover handler should follow "tbegin.;" */ + "mflr 31;" + "bl 4f;" /* $ = TFHAR - 12 */ + "4: ;" + "mflr %[tfhar];" + "mtlr 31;" + + "tbegin.;" + "beq 2f;" + + "tsuspend.;" + "li 8, 1;" + "sth 8, 0(%[cptr1]);" + "tresume.;" + "b .;" + + "tend.;" + "li 0, 0;" + "ori %[res], 0, 0;" + "b 3f;" + + "2: ;" + + "li 0, 1;" + "ori %[res], 0, 0;" + "mfspr %[texasr], %[sprn_texasr];" + + "3: ;" + : [tfhar] "=r" (tfhar), [res] "=r" (result), + [texasr] "=r" (texasr), [cptr1] "=r" (cptr1) + : [sprn_texasr] "i" (SPRN_TEXASR) + : "memory", "r0", "r1", "r2", "r3", "r4", + "r8", "r9", "r10", "r11", "r31" + ); + + /* There are 2 32bit instructions before tbegin. */ + tfhar += 12; + + if (result) { + if (!cptr->flag) + goto trans; + + ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs); + shmdt((void *)cptr); + shmdt((void *)cptr1); + if (ret) + exit(1); + exit(0); + } + shmdt((void *)cptr); + shmdt((void *)cptr1); + exit(1); +} + +int trace_tm_spr(pid_t child) +{ + FAIL_IF(start_trace(child)); + FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs)); + + printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar, + pptr->regs.tm_texasr, pptr->regs.tm_tfiar); + + pptr->flag = 1; + FAIL_IF(stop_trace(child)); + + return TEST_PASS; +} + +int ptrace_tm_spr(void) +{ + pid_t pid; + int ret, status; + + SKIP_IF(!have_htm()); + shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT); + shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT); + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + return TEST_FAIL; + } + + if (pid == 0) + tm_spr(); + + if (pid) { + pptr = (struct shared *)shmat(shm_id, NULL, 0); + pptr1 = (int *)shmat(shm_id1, NULL, 0); + + while (!pptr1[0]) + asm volatile("" : : : "memory"); + ret = trace_tm_spr(pid); + if (ret) { + kill(pid, SIGKILL); + shmdt((void *)pptr); + shmdt((void *)pptr1); + shmctl(shm_id, IPC_RMID, NULL); + shmctl(shm_id1, IPC_RMID, NULL); + return TEST_FAIL; + } + + shmdt((void *)pptr); + shmdt((void *)pptr1); + ret = wait(&status); + shmctl(shm_id, IPC_RMID, NULL); + shmctl(shm_id1, IPC_RMID, NULL); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } + + return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL : + TEST_PASS; + } + return TEST_PASS; +} + +int main(int argc, char *argv[]) +{ + return test_harness(ptrace_tm_spr, "ptrace_tm_spr"); +} diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h index 9aa0498..19fb8252 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace.h +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h @@ -38,6 +38,11 @@ struct fpr_regs { unsigned long fpscr; }; +struct tm_spr_regs { + unsigned long tm_tfhar; + unsigned long tm_texasr; + unsigned long tm_tfiar; +}; #ifndef NT_PPC_TAR #define NT_PPC_TAR 0x103 @@ -605,6 +610,36 @@ int write_vsx_ckpt(pid_t child, unsigned long *vsx) return TEST_PASS; } +/* TM SPR */ +int show_tm_spr(pid_t child, struct tm_spr_regs *out) +{ + struct tm_spr_regs *regs; + struct iovec iov; + int ret; + + regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs)); + if (!regs) { + perror("malloc() failed"); + return TEST_FAIL; + } + + iov.iov_base = (u64 *) regs; + iov.iov_len = sizeof(struct tm_spr_regs); + + ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov); + if (ret) { + perror("ptrace(PTRACE_GETREGSET) failed"); + return TEST_FAIL; + } + + if (out) + memcpy(out, regs, sizeof(struct tm_spr_regs)); + + return TEST_PASS; +} + + + /* Analyse TEXASR after TM failure */ inline unsigned long get_tfiar(void) { -- cgit v1.1