xref: /openbmc/linux/tools/testing/selftests/powerpc/ptrace/ptrace-tm-vsx.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
211508074SAnshuman Khandual /*
311508074SAnshuman Khandual  * Ptrace test for VMX/VSX registers in the TM context
411508074SAnshuman Khandual  *
511508074SAnshuman Khandual  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
611508074SAnshuman Khandual  */
711508074SAnshuman Khandual #include "ptrace.h"
811508074SAnshuman Khandual #include "tm.h"
911508074SAnshuman Khandual #include "ptrace-vsx.h"
1011508074SAnshuman Khandual 
1111508074SAnshuman Khandual int shm_id;
1211508074SAnshuman Khandual unsigned long *cptr, *pptr;
1311508074SAnshuman Khandual 
1411508074SAnshuman Khandual unsigned long fp_load[VEC_MAX];
1511508074SAnshuman Khandual unsigned long fp_store[VEC_MAX];
1611508074SAnshuman Khandual unsigned long fp_load_ckpt[VEC_MAX];
1711508074SAnshuman Khandual unsigned long fp_load_ckpt_new[VEC_MAX];
1811508074SAnshuman Khandual 
load_vsx(void)1911508074SAnshuman Khandual __attribute__((used)) void load_vsx(void)
2011508074SAnshuman Khandual {
2111508074SAnshuman Khandual 	loadvsx(fp_load, 0);
2211508074SAnshuman Khandual }
2311508074SAnshuman Khandual 
load_vsx_ckpt(void)2411508074SAnshuman Khandual __attribute__((used)) void load_vsx_ckpt(void)
2511508074SAnshuman Khandual {
2611508074SAnshuman Khandual 	loadvsx(fp_load_ckpt, 0);
2711508074SAnshuman Khandual }
2811508074SAnshuman Khandual 
tm_vsx(void)2911508074SAnshuman Khandual void tm_vsx(void)
3011508074SAnshuman Khandual {
3111508074SAnshuman Khandual 	unsigned long result, texasr;
3211508074SAnshuman Khandual 	int ret;
3311508074SAnshuman Khandual 
3411508074SAnshuman Khandual 	cptr = (unsigned long *)shmat(shm_id, NULL, 0);
3511508074SAnshuman Khandual 
3611508074SAnshuman Khandual trans:
3711508074SAnshuman Khandual 	cptr[1] = 0;
3811508074SAnshuman Khandual 	asm __volatile__(
3911508074SAnshuman Khandual 		"bl load_vsx_ckpt;"
4011508074SAnshuman Khandual 
4111508074SAnshuman Khandual 		"1: ;"
4211508074SAnshuman Khandual 		"tbegin.;"
4311508074SAnshuman Khandual 		"beq 2f;"
4411508074SAnshuman Khandual 
4511508074SAnshuman Khandual 		"bl load_vsx;"
4611508074SAnshuman Khandual 		"tsuspend.;"
4711508074SAnshuman Khandual 		"li 7, 1;"
4811508074SAnshuman Khandual 		"stw 7, 0(%[cptr1]);"
4911508074SAnshuman Khandual 		"tresume.;"
5011508074SAnshuman Khandual 		"b .;"
5111508074SAnshuman Khandual 
5211508074SAnshuman Khandual 		"tend.;"
5311508074SAnshuman Khandual 		"li 0, 0;"
5411508074SAnshuman Khandual 		"ori %[res], 0, 0;"
5511508074SAnshuman Khandual 		"b 3f;"
5611508074SAnshuman Khandual 
5711508074SAnshuman Khandual 		"2: ;"
5811508074SAnshuman Khandual 		"li 0, 1;"
5911508074SAnshuman Khandual 		"ori %[res], 0, 0;"
6011508074SAnshuman Khandual 		"mfspr %[texasr], %[sprn_texasr];"
6111508074SAnshuman Khandual 
6211508074SAnshuman Khandual 		"3: ;"
6311508074SAnshuman Khandual 		: [res] "=r" (result), [texasr] "=r" (texasr)
645249497aSBreno Leitao 		: [sprn_texasr] "i"  (SPRN_TEXASR), [cptr1] "b" (&cptr[1])
65a02cbc7fSMichael Ellerman 		: "memory", "r0", "r3", "r4",
66a02cbc7fSMichael Ellerman 		  "r7", "r8", "r9", "r10", "r11", "lr"
6711508074SAnshuman Khandual 		);
6811508074SAnshuman Khandual 
6911508074SAnshuman Khandual 	if (result) {
7011508074SAnshuman Khandual 		if (!cptr[0])
7111508074SAnshuman Khandual 			goto trans;
7211508074SAnshuman Khandual 
7311508074SAnshuman Khandual 		shmdt((void *)cptr);
7411508074SAnshuman Khandual 		storevsx(fp_store, 0);
7511508074SAnshuman Khandual 		ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new);
7611508074SAnshuman Khandual 		if (ret)
7711508074SAnshuman Khandual 			exit(1);
7811508074SAnshuman Khandual 		exit(0);
7911508074SAnshuman Khandual 	}
8011508074SAnshuman Khandual 	shmdt((void *)cptr);
8111508074SAnshuman Khandual 	exit(1);
8211508074SAnshuman Khandual }
8311508074SAnshuman Khandual 
trace_tm_vsx(pid_t child)8411508074SAnshuman Khandual int trace_tm_vsx(pid_t child)
8511508074SAnshuman Khandual {
8611508074SAnshuman Khandual 	unsigned long vsx[VSX_MAX];
8711508074SAnshuman Khandual 	unsigned long vmx[VMX_MAX + 2][2];
8811508074SAnshuman Khandual 
8911508074SAnshuman Khandual 	FAIL_IF(start_trace(child));
9011508074SAnshuman Khandual 	FAIL_IF(show_vsx(child, vsx));
9111508074SAnshuman Khandual 	FAIL_IF(validate_vsx(vsx, fp_load));
9211508074SAnshuman Khandual 	FAIL_IF(show_vmx(child, vmx));
9311508074SAnshuman Khandual 	FAIL_IF(validate_vmx(vmx, fp_load));
9411508074SAnshuman Khandual 	FAIL_IF(show_vsx_ckpt(child, vsx));
9511508074SAnshuman Khandual 	FAIL_IF(validate_vsx(vsx, fp_load_ckpt));
9611508074SAnshuman Khandual 	FAIL_IF(show_vmx_ckpt(child, vmx));
9711508074SAnshuman Khandual 	FAIL_IF(validate_vmx(vmx, fp_load_ckpt));
9811508074SAnshuman Khandual 	memset(vsx, 0, sizeof(vsx));
9911508074SAnshuman Khandual 	memset(vmx, 0, sizeof(vmx));
10011508074SAnshuman Khandual 
10111508074SAnshuman Khandual 	load_vsx_vmx(fp_load_ckpt_new, vsx, vmx);
10211508074SAnshuman Khandual 
10311508074SAnshuman Khandual 	FAIL_IF(write_vsx_ckpt(child, vsx));
10411508074SAnshuman Khandual 	FAIL_IF(write_vmx_ckpt(child, vmx));
10511508074SAnshuman Khandual 	pptr[0] = 1;
10611508074SAnshuman Khandual 	FAIL_IF(stop_trace(child));
10711508074SAnshuman Khandual 	return TEST_PASS;
10811508074SAnshuman Khandual }
10911508074SAnshuman Khandual 
ptrace_tm_vsx(void)11011508074SAnshuman Khandual int ptrace_tm_vsx(void)
11111508074SAnshuman Khandual {
11211508074SAnshuman Khandual 	pid_t pid;
11311508074SAnshuman Khandual 	int ret, status, i;
11411508074SAnshuman Khandual 
115*68877ff2SBenjamin Gray 	SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
116*68877ff2SBenjamin Gray 	SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
11711508074SAnshuman Khandual 	shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
11811508074SAnshuman Khandual 
11911508074SAnshuman Khandual 	for (i = 0; i < 128; i++) {
12011508074SAnshuman Khandual 		fp_load[i] = 1 + rand();
12111508074SAnshuman Khandual 		fp_load_ckpt[i] = 1 + 2 * rand();
12211508074SAnshuman Khandual 		fp_load_ckpt_new[i] = 1 + 3 * rand();
12311508074SAnshuman Khandual 	}
12411508074SAnshuman Khandual 
12511508074SAnshuman Khandual 	pid = fork();
12611508074SAnshuman Khandual 	if (pid < 0) {
12711508074SAnshuman Khandual 		perror("fork() failed");
12811508074SAnshuman Khandual 		return TEST_FAIL;
12911508074SAnshuman Khandual 	}
13011508074SAnshuman Khandual 
13111508074SAnshuman Khandual 	if (pid == 0)
13211508074SAnshuman Khandual 		tm_vsx();
13311508074SAnshuman Khandual 
13411508074SAnshuman Khandual 	if (pid) {
13511508074SAnshuman Khandual 		pptr = (unsigned long *)shmat(shm_id, NULL, 0);
13611508074SAnshuman Khandual 		while (!pptr[1])
13711508074SAnshuman Khandual 			asm volatile("" : : : "memory");
13811508074SAnshuman Khandual 
13911508074SAnshuman Khandual 		ret = trace_tm_vsx(pid);
14011508074SAnshuman Khandual 		if (ret) {
14111508074SAnshuman Khandual 			kill(pid, SIGKILL);
14211508074SAnshuman Khandual 			shmdt((void *)pptr);
14311508074SAnshuman Khandual 			shmctl(shm_id, IPC_RMID, NULL);
14411508074SAnshuman Khandual 			return TEST_FAIL;
14511508074SAnshuman Khandual 		}
14611508074SAnshuman Khandual 
14711508074SAnshuman Khandual 		shmdt((void *)pptr);
14811508074SAnshuman Khandual 		ret = wait(&status);
14911508074SAnshuman Khandual 		shmctl(shm_id, IPC_RMID, NULL);
15011508074SAnshuman Khandual 		if (ret != pid) {
15111508074SAnshuman Khandual 			printf("Child's exit status not captured\n");
15211508074SAnshuman Khandual 			return TEST_FAIL;
15311508074SAnshuman Khandual 		}
15411508074SAnshuman Khandual 
15511508074SAnshuman Khandual 		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
15611508074SAnshuman Khandual 			TEST_PASS;
15711508074SAnshuman Khandual 	}
15811508074SAnshuman Khandual 	return TEST_PASS;
15911508074SAnshuman Khandual }
16011508074SAnshuman Khandual 
main(int argc,char * argv[])16111508074SAnshuman Khandual int main(int argc, char *argv[])
16211508074SAnshuman Khandual {
16311508074SAnshuman Khandual 	return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx");
16411508074SAnshuman Khandual }
165