| /* | |
| * 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 <inttypes.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <sys/mman.h> | |
| #include <string.h> | |
| #include <assert.h> | |
| #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"); | |
| } |