Transactional Memory was removed from the architecture in ISA v3.1. For threads running in P8/P9 compatibility mode on P10 a synthetic TM implementation is provided. In this implementation, tbegin. always sets cr0 eq meaning the abort handler is always called. This is not an issue as users of TM are expected to have a fallback non transactional way to make forward progress in the abort handler. The TEXASR indicates if a transaction failure is due to a synthetic implementation. Some of the TM self tests need a non-degenerate TM implementation for their testing to be meaningful so check for a synthetic implementation and skip the test if so. Signed-off-by: Jordan Niethe <jniethe5@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20210729041317.366612-2-jniethe5@gmail.com
105 lines
2.2 KiB
C
105 lines
2.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright 2015, Michael Neuling, IBM Corp.
|
|
*
|
|
* 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());
|
|
SKIP_IF(htm_is_synthetic());
|
|
SKIP_IF(!is_ppc64le());
|
|
|
|
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");
|
|
}
|