From 5f337e3e5b04b32793fd51adab438d46df99c933 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Thu, 10 Dec 2015 20:49:33 +1100 Subject: selftests/powerpc: Add test to check if VSRs are corrupted When a transaction is aborted, VSR values should rollback to the checkpointed values before the transaction began. VSRs used elsewhere in the kernel during a transaction, or while the transaction is suspended should not affect the checkpointed values. Prior to the bug fix in commit d31626f70b61 ("powerpc: Don't corrupt transactional state when using FP/VMX in kernel") when VMX was requested by the kernel the .vr_state (which held the checkpointed state of VSRs before the transaction) was overwritten with the current state from outside the transation. Thus if the transaction did not complete, the VSR values would be "rolled back" to potentially incorrect values. Signed-off-by: Rashmica Gupta Signed-off-by: Michael Ellerman --- tools/testing/selftests/powerpc/tm/.gitignore | 1 + tools/testing/selftests/powerpc/tm/Makefile | 2 +- tools/testing/selftests/powerpc/tm/tm-vmxcopy.c | 103 ++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-vmxcopy.c (limited to 'tools/testing') diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore index e6668217ccd0..7d0f14b8cb2e 100644 --- a/tools/testing/selftests/powerpc/tm/.gitignore +++ b/tools/testing/selftests/powerpc/tm/.gitignore @@ -2,3 +2,4 @@ tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack +tm-vmxcopy diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index e7ceff809fa0..737f72c964e6 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile @@ -1,4 +1,4 @@ -TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack +TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy all: $(TEST_PROGS) diff --git a/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c new file mode 100644 index 000000000000..0274de7b11f3 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-vmxcopy.c @@ -0,0 +1,103 @@ +/* + * Copyright 2015, Michael Neuling, IBM Corp. + * Licensed under GPLv2. + * + * Original: Michael Neuling 4/12/2013 + * Edited: Rashmica Gupta 4/12/2015 + * + * See if the altivec state is leaked out of an aborted transaction due to + * kernel vmx copy loops. + * + * When the transaction aborts, VSR values should rollback to the values + * they held before the transaction commenced. Using VSRs while transaction + * is suspended should not affect the checkpointed values. + * + * (1) write A to a VSR + * (2) start transaction + * (3) suspend transaction + * (4) change the VSR to B + * (5) trigger kernel vmx copy loop + * (6) abort transaction + * (7) check that the VSR value is A + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tm.h" +#include "utils.h" + +int test_vmxcopy() +{ + long double vecin = 1.3; + long double vecout; + unsigned long pgsize = getpagesize(); + int i; + int fd; + int size = pgsize*16; + char tmpfile[] = "/tmp/page_faultXXXXXX"; + char buf[pgsize]; + char *a; + uint64_t aborted = 0; + + SKIP_IF(!have_htm()); + + fd = mkstemp(tmpfile); + assert(fd >= 0); + + memset(buf, 0, pgsize); + for (i = 0; i < size; i += pgsize) + assert(write(fd, buf, pgsize) == pgsize); + + unlink(tmpfile); + + a = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + assert(a != MAP_FAILED); + + asm __volatile__( + "lxvd2x 40,0,%[vecinptr];" /* set 40 to initial value*/ + "tbegin.;" + "beq 3f;" + "tsuspend.;" + "xxlxor 40,40,40;" /* set 40 to 0 */ + "std 5, 0(%[map]);" /* cause kernel vmx copy page */ + "tabort. 0;" + "tresume.;" + "tend.;" + "li %[res], 0;" + "b 5f;" + + /* Abort handler */ + "3:;" + "li %[res], 1;" + + "5:;" + "stxvd2x 40,0,%[vecoutptr];" + : [res]"=r"(aborted) + : [vecinptr]"r"(&vecin), + [vecoutptr]"r"(&vecout), + [map]"r"(a) + : "memory", "r0", "r3", "r4", "r5", "r6", "r7"); + + if (aborted && (vecin != vecout)){ + printf("FAILED: vector state leaked on abort %f != %f\n", + (double)vecin, (double)vecout); + return 1; + } + + munmap(a, size); + + close(fd); + + return 0; +} + +int main(void) +{ + return test_harness(test_vmxcopy, "tm_vmxcopy"); +} -- cgit v1.2.3