xref: /openbmc/linux/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-tar.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
201f7fdc7SAnshuman Khandual /*
301f7fdc7SAnshuman Khandual  * Ptrace test for TAR, PPR, DSCR registers in the TM Suspend context
401f7fdc7SAnshuman Khandual  *
501f7fdc7SAnshuman Khandual  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
601f7fdc7SAnshuman Khandual  */
701f7fdc7SAnshuman Khandual #include "ptrace.h"
801f7fdc7SAnshuman Khandual #include "tm.h"
901f7fdc7SAnshuman Khandual #include "ptrace-tar.h"
1001f7fdc7SAnshuman Khandual 
1101f7fdc7SAnshuman Khandual int shm_id;
1201f7fdc7SAnshuman Khandual int *cptr, *pptr;
1301f7fdc7SAnshuman Khandual 
wait_parent(void)1401f7fdc7SAnshuman Khandual __attribute__((used)) void wait_parent(void)
1501f7fdc7SAnshuman Khandual {
1601f7fdc7SAnshuman Khandual 	cptr[2] = 1;
1701f7fdc7SAnshuman Khandual 	while (!cptr[1])
1801f7fdc7SAnshuman Khandual 		asm volatile("" : : : "memory");
1901f7fdc7SAnshuman Khandual }
2001f7fdc7SAnshuman Khandual 
tm_spd_tar(void)2101f7fdc7SAnshuman Khandual void tm_spd_tar(void)
2201f7fdc7SAnshuman Khandual {
2301f7fdc7SAnshuman Khandual 	unsigned long result, texasr;
2401f7fdc7SAnshuman Khandual 	unsigned long regs[3];
2501f7fdc7SAnshuman Khandual 	int ret;
2601f7fdc7SAnshuman Khandual 
2701f7fdc7SAnshuman Khandual 	cptr = (int *)shmat(shm_id, NULL, 0);
2801f7fdc7SAnshuman Khandual 
2901f7fdc7SAnshuman Khandual trans:
3001f7fdc7SAnshuman Khandual 	cptr[2] = 0;
3101f7fdc7SAnshuman Khandual 	asm __volatile__(
3201f7fdc7SAnshuman Khandual 		"li	4, %[tar_1];"
3301f7fdc7SAnshuman Khandual 		"mtspr %[sprn_tar],  4;"	/* TAR_1 */
3401f7fdc7SAnshuman Khandual 		"li	4, %[dscr_1];"
3501f7fdc7SAnshuman Khandual 		"mtspr %[sprn_dscr], 4;"	/* DSCR_1 */
3601f7fdc7SAnshuman Khandual 		"or     31,31,31;"		/* PPR_1*/
3701f7fdc7SAnshuman Khandual 
3801f7fdc7SAnshuman Khandual 		"1: ;"
3901f7fdc7SAnshuman Khandual 		"tbegin.;"
4001f7fdc7SAnshuman Khandual 		"beq 2f;"
4101f7fdc7SAnshuman Khandual 
4201f7fdc7SAnshuman Khandual 		"li	4, %[tar_2];"
4301f7fdc7SAnshuman Khandual 		"mtspr %[sprn_tar],  4;"	/* TAR_2 */
4401f7fdc7SAnshuman Khandual 		"li	4, %[dscr_2];"
4501f7fdc7SAnshuman Khandual 		"mtspr %[sprn_dscr], 4;"	/* DSCR_2 */
4601f7fdc7SAnshuman Khandual 		"or     1,1,1;"			/* PPR_2 */
4701f7fdc7SAnshuman Khandual 
4801f7fdc7SAnshuman Khandual 		"tsuspend.;"
4901f7fdc7SAnshuman Khandual 		"li	4, %[tar_3];"
5001f7fdc7SAnshuman Khandual 		"mtspr %[sprn_tar],  4;"	/* TAR_3 */
5101f7fdc7SAnshuman Khandual 		"li	4, %[dscr_3];"
5201f7fdc7SAnshuman Khandual 		"mtspr %[sprn_dscr], 4;"	/* DSCR_3 */
5301f7fdc7SAnshuman Khandual 		"or     6,6,6;"			/* PPR_3 */
5401f7fdc7SAnshuman Khandual 		"bl wait_parent;"
5501f7fdc7SAnshuman Khandual 		"tresume.;"
5601f7fdc7SAnshuman Khandual 
5701f7fdc7SAnshuman Khandual 		"tend.;"
5801f7fdc7SAnshuman Khandual 		"li 0, 0;"
5901f7fdc7SAnshuman Khandual 		"ori %[res], 0, 0;"
6001f7fdc7SAnshuman Khandual 		"b 3f;"
6101f7fdc7SAnshuman Khandual 
6201f7fdc7SAnshuman Khandual 		/* Transaction abort handler */
6301f7fdc7SAnshuman Khandual 		"2: ;"
6401f7fdc7SAnshuman Khandual 		"li 0, 1;"
6501f7fdc7SAnshuman Khandual 		"ori %[res], 0, 0;"
6601f7fdc7SAnshuman Khandual 		"mfspr %[texasr], %[sprn_texasr];"
6701f7fdc7SAnshuman Khandual 
6801f7fdc7SAnshuman Khandual 		"3: ;"
6901f7fdc7SAnshuman Khandual 
7001f7fdc7SAnshuman Khandual 		: [res] "=r" (result), [texasr] "=r" (texasr)
715249497aSBreno Leitao 		: [sprn_dscr]"i"(SPRN_DSCR),
7201f7fdc7SAnshuman Khandual 		[sprn_tar]"i"(SPRN_TAR), [sprn_ppr]"i"(SPRN_PPR),
7301f7fdc7SAnshuman Khandual 		[sprn_texasr]"i"(SPRN_TEXASR), [tar_1]"i"(TAR_1),
7401f7fdc7SAnshuman Khandual 		[dscr_1]"i"(DSCR_1), [tar_2]"i"(TAR_2), [dscr_2]"i"(DSCR_2),
7501f7fdc7SAnshuman Khandual 		[tar_3]"i"(TAR_3), [dscr_3]"i"(DSCR_3)
76a02cbc7fSMichael Ellerman 		: "memory", "r0", "r3", "r4", "r5", "r6", "lr"
7701f7fdc7SAnshuman Khandual 		);
7801f7fdc7SAnshuman Khandual 
7901f7fdc7SAnshuman Khandual 	/* TM failed, analyse */
8001f7fdc7SAnshuman Khandual 	if (result) {
8101f7fdc7SAnshuman Khandual 		if (!cptr[0])
8201f7fdc7SAnshuman Khandual 			goto trans;
8301f7fdc7SAnshuman Khandual 
8401f7fdc7SAnshuman Khandual 		regs[0] = mfspr(SPRN_TAR);
8501f7fdc7SAnshuman Khandual 		regs[1] = mfspr(SPRN_PPR);
8601f7fdc7SAnshuman Khandual 		regs[2] = mfspr(SPRN_DSCR);
8701f7fdc7SAnshuman Khandual 
8801f7fdc7SAnshuman Khandual 		shmdt(&cptr);
8901f7fdc7SAnshuman Khandual 		printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
9001f7fdc7SAnshuman Khandual 				user_read, regs[0], regs[1], regs[2]);
9101f7fdc7SAnshuman Khandual 
9201f7fdc7SAnshuman Khandual 		ret = validate_tar_registers(regs, TAR_4, PPR_4, DSCR_4);
9301f7fdc7SAnshuman Khandual 		if (ret)
9401f7fdc7SAnshuman Khandual 			exit(1);
9501f7fdc7SAnshuman Khandual 		exit(0);
9601f7fdc7SAnshuman Khandual 	}
9701f7fdc7SAnshuman Khandual 	shmdt(&cptr);
9801f7fdc7SAnshuman Khandual 	exit(1);
9901f7fdc7SAnshuman Khandual }
10001f7fdc7SAnshuman Khandual 
trace_tm_spd_tar(pid_t child)10101f7fdc7SAnshuman Khandual int trace_tm_spd_tar(pid_t child)
10201f7fdc7SAnshuman Khandual {
10301f7fdc7SAnshuman Khandual 	unsigned long regs[3];
10401f7fdc7SAnshuman Khandual 
10501f7fdc7SAnshuman Khandual 	FAIL_IF(start_trace(child));
10601f7fdc7SAnshuman Khandual 	FAIL_IF(show_tar_registers(child, regs));
10701f7fdc7SAnshuman Khandual 	printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
10801f7fdc7SAnshuman Khandual 			ptrace_read_running, regs[0], regs[1], regs[2]);
10901f7fdc7SAnshuman Khandual 
11001f7fdc7SAnshuman Khandual 	FAIL_IF(validate_tar_registers(regs, TAR_3, PPR_3, DSCR_3));
11101f7fdc7SAnshuman Khandual 	FAIL_IF(show_tm_checkpointed_state(child, regs));
11201f7fdc7SAnshuman Khandual 	printf("%-30s TAR: %lu PPR: %lx DSCR: %lu\n",
11301f7fdc7SAnshuman Khandual 			ptrace_read_ckpt, regs[0], regs[1], regs[2]);
11401f7fdc7SAnshuman Khandual 
11501f7fdc7SAnshuman Khandual 	FAIL_IF(validate_tar_registers(regs, TAR_1, PPR_1, DSCR_1));
11601f7fdc7SAnshuman Khandual 	FAIL_IF(write_ckpt_tar_registers(child, TAR_4, PPR_4, DSCR_4));
11701f7fdc7SAnshuman Khandual 	printf("%-30s TAR: %u PPR: %lx DSCR: %u\n",
11801f7fdc7SAnshuman Khandual 			ptrace_write_ckpt, TAR_4, PPR_4, DSCR_4);
11901f7fdc7SAnshuman Khandual 
12001f7fdc7SAnshuman Khandual 	pptr[0] = 1;
12101f7fdc7SAnshuman Khandual 	pptr[1] = 1;
12201f7fdc7SAnshuman Khandual 	FAIL_IF(stop_trace(child));
12301f7fdc7SAnshuman Khandual 	return TEST_PASS;
12401f7fdc7SAnshuman Khandual }
12501f7fdc7SAnshuman Khandual 
ptrace_tm_spd_tar(void)12601f7fdc7SAnshuman Khandual int ptrace_tm_spd_tar(void)
12701f7fdc7SAnshuman Khandual {
12801f7fdc7SAnshuman Khandual 	pid_t pid;
12901f7fdc7SAnshuman Khandual 	int ret, status;
13001f7fdc7SAnshuman Khandual 
131*68877ff2SBenjamin Gray 	SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
132*68877ff2SBenjamin Gray 	SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
13301f7fdc7SAnshuman Khandual 	shm_id = shmget(IPC_PRIVATE, sizeof(int) * 3, 0777|IPC_CREAT);
13401f7fdc7SAnshuman Khandual 	pid = fork();
13501f7fdc7SAnshuman Khandual 	if (pid == 0)
13601f7fdc7SAnshuman Khandual 		tm_spd_tar();
13701f7fdc7SAnshuman Khandual 
13801f7fdc7SAnshuman Khandual 	pptr = (int *)shmat(shm_id, NULL, 0);
13901f7fdc7SAnshuman Khandual 	pptr[0] = 0;
14001f7fdc7SAnshuman Khandual 	pptr[1] = 0;
14101f7fdc7SAnshuman Khandual 
14201f7fdc7SAnshuman Khandual 	if (pid) {
14301f7fdc7SAnshuman Khandual 		while (!pptr[2])
14401f7fdc7SAnshuman Khandual 			asm volatile("" : : : "memory");
14501f7fdc7SAnshuman Khandual 		ret = trace_tm_spd_tar(pid);
14601f7fdc7SAnshuman Khandual 		if (ret) {
14701f7fdc7SAnshuman Khandual 			kill(pid, SIGTERM);
14801f7fdc7SAnshuman Khandual 			shmdt(&pptr);
14901f7fdc7SAnshuman Khandual 			shmctl(shm_id, IPC_RMID, NULL);
15001f7fdc7SAnshuman Khandual 			return TEST_FAIL;
15101f7fdc7SAnshuman Khandual 		}
15201f7fdc7SAnshuman Khandual 
15301f7fdc7SAnshuman Khandual 		shmdt(&pptr);
15401f7fdc7SAnshuman Khandual 
15501f7fdc7SAnshuman Khandual 		ret = wait(&status);
15601f7fdc7SAnshuman Khandual 		shmctl(shm_id, IPC_RMID, NULL);
15701f7fdc7SAnshuman Khandual 		if (ret != pid) {
15801f7fdc7SAnshuman Khandual 			printf("Child's exit status not captured\n");
15901f7fdc7SAnshuman Khandual 			return TEST_FAIL;
16001f7fdc7SAnshuman Khandual 		}
16101f7fdc7SAnshuman Khandual 
16201f7fdc7SAnshuman Khandual 		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
16301f7fdc7SAnshuman Khandual 			TEST_PASS;
16401f7fdc7SAnshuman Khandual 	}
16501f7fdc7SAnshuman Khandual 	return TEST_PASS;
16601f7fdc7SAnshuman Khandual }
16701f7fdc7SAnshuman Khandual 
main(int argc,char * argv[])16801f7fdc7SAnshuman Khandual int main(int argc, char *argv[])
16901f7fdc7SAnshuman Khandual {
17001f7fdc7SAnshuman Khandual 	return test_harness(ptrace_tm_spd_tar, "ptrace_tm_spd_tar");
17101f7fdc7SAnshuman Khandual }
172