18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2015, Michael Neuling, IBM Corp. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Original: Michael Neuling 4/12/2013 68c2ecf20Sopenharmony_ci * Edited: Rashmica Gupta 4/12/2015 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * See if the altivec state is leaked out of an aborted transaction due to 98c2ecf20Sopenharmony_ci * kernel vmx copy loops. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * When the transaction aborts, VSR values should rollback to the values 128c2ecf20Sopenharmony_ci * they held before the transaction commenced. Using VSRs while transaction 138c2ecf20Sopenharmony_ci * is suspended should not affect the checkpointed values. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * (1) write A to a VSR 168c2ecf20Sopenharmony_ci * (2) start transaction 178c2ecf20Sopenharmony_ci * (3) suspend transaction 188c2ecf20Sopenharmony_ci * (4) change the VSR to B 198c2ecf20Sopenharmony_ci * (5) trigger kernel vmx copy loop 208c2ecf20Sopenharmony_ci * (6) abort transaction 218c2ecf20Sopenharmony_ci * (7) check that the VSR value is A 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <inttypes.h> 258c2ecf20Sopenharmony_ci#include <stdio.h> 268c2ecf20Sopenharmony_ci#include <stdlib.h> 278c2ecf20Sopenharmony_ci#include <unistd.h> 288c2ecf20Sopenharmony_ci#include <sys/mman.h> 298c2ecf20Sopenharmony_ci#include <string.h> 308c2ecf20Sopenharmony_ci#include <assert.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "tm.h" 338c2ecf20Sopenharmony_ci#include "utils.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciint test_vmxcopy() 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci long double vecin = 1.3; 388c2ecf20Sopenharmony_ci long double vecout; 398c2ecf20Sopenharmony_ci unsigned long pgsize = getpagesize(); 408c2ecf20Sopenharmony_ci int i; 418c2ecf20Sopenharmony_ci int fd; 428c2ecf20Sopenharmony_ci int size = pgsize*16; 438c2ecf20Sopenharmony_ci char tmpfile[] = "/tmp/page_faultXXXXXX"; 448c2ecf20Sopenharmony_ci char buf[pgsize]; 458c2ecf20Sopenharmony_ci char *a; 468c2ecf20Sopenharmony_ci uint64_t aborted = 0; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci SKIP_IF(!have_htm()); 498c2ecf20Sopenharmony_ci SKIP_IF(!is_ppc64le()); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci fd = mkstemp(tmpfile); 528c2ecf20Sopenharmony_ci assert(fd >= 0); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci memset(buf, 0, pgsize); 558c2ecf20Sopenharmony_ci for (i = 0; i < size; i += pgsize) 568c2ecf20Sopenharmony_ci assert(write(fd, buf, pgsize) == pgsize); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci unlink(tmpfile); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci a = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 618c2ecf20Sopenharmony_ci assert(a != MAP_FAILED); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci asm __volatile__( 648c2ecf20Sopenharmony_ci "lxvd2x 40,0,%[vecinptr];" /* set 40 to initial value*/ 658c2ecf20Sopenharmony_ci "tbegin.;" 668c2ecf20Sopenharmony_ci "beq 3f;" 678c2ecf20Sopenharmony_ci "tsuspend.;" 688c2ecf20Sopenharmony_ci "xxlxor 40,40,40;" /* set 40 to 0 */ 698c2ecf20Sopenharmony_ci "std 5, 0(%[map]);" /* cause kernel vmx copy page */ 708c2ecf20Sopenharmony_ci "tabort. 0;" 718c2ecf20Sopenharmony_ci "tresume.;" 728c2ecf20Sopenharmony_ci "tend.;" 738c2ecf20Sopenharmony_ci "li %[res], 0;" 748c2ecf20Sopenharmony_ci "b 5f;" 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* Abort handler */ 778c2ecf20Sopenharmony_ci "3:;" 788c2ecf20Sopenharmony_ci "li %[res], 1;" 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci "5:;" 818c2ecf20Sopenharmony_ci "stxvd2x 40,0,%[vecoutptr];" 828c2ecf20Sopenharmony_ci : [res]"=&r"(aborted) 838c2ecf20Sopenharmony_ci : [vecinptr]"r"(&vecin), 848c2ecf20Sopenharmony_ci [vecoutptr]"r"(&vecout), 858c2ecf20Sopenharmony_ci [map]"r"(a) 868c2ecf20Sopenharmony_ci : "memory", "r0", "r3", "r4", "r5", "r6", "r7"); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci if (aborted && (vecin != vecout)){ 898c2ecf20Sopenharmony_ci printf("FAILED: vector state leaked on abort %f != %f\n", 908c2ecf20Sopenharmony_ci (double)vecin, (double)vecout); 918c2ecf20Sopenharmony_ci return 1; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci munmap(a, size); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci close(fd); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciint main(void) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci return test_harness(test_vmxcopy, "tm_vmxcopy"); 1048c2ecf20Sopenharmony_ci} 105