xref: /openbmc/linux/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spr.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
25bdac52fSAnshuman Khandual /*
35bdac52fSAnshuman Khandual  * Ptrace test TM SPR registers
45bdac52fSAnshuman Khandual  *
55bdac52fSAnshuman Khandual  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
65bdac52fSAnshuman Khandual  */
75bdac52fSAnshuman Khandual #include "ptrace.h"
85bdac52fSAnshuman Khandual #include "tm.h"
95bdac52fSAnshuman Khandual 
105bdac52fSAnshuman Khandual /* Tracee and tracer shared data */
115bdac52fSAnshuman Khandual struct shared {
125bdac52fSAnshuman Khandual 	int flag;
135bdac52fSAnshuman Khandual 	struct tm_spr_regs regs;
145bdac52fSAnshuman Khandual };
155bdac52fSAnshuman Khandual unsigned long tfhar;
165bdac52fSAnshuman Khandual 
175bdac52fSAnshuman Khandual int shm_id;
185bdac52fSAnshuman Khandual struct shared *cptr, *pptr;
195bdac52fSAnshuman Khandual 
205bdac52fSAnshuman Khandual int shm_id1;
215bdac52fSAnshuman Khandual int *cptr1, *pptr1;
225bdac52fSAnshuman Khandual 
235bdac52fSAnshuman Khandual #define TM_KVM_SCHED   0xe0000001ac000001
validate_tm_spr(struct tm_spr_regs * regs)245bdac52fSAnshuman Khandual int validate_tm_spr(struct tm_spr_regs *regs)
255bdac52fSAnshuman Khandual {
265bdac52fSAnshuman Khandual 	FAIL_IF(regs->tm_tfhar != tfhar);
275bdac52fSAnshuman Khandual 	FAIL_IF((regs->tm_texasr == TM_KVM_SCHED) && (regs->tm_tfiar != 0));
285bdac52fSAnshuman Khandual 
295bdac52fSAnshuman Khandual 	return TEST_PASS;
305bdac52fSAnshuman Khandual }
315bdac52fSAnshuman Khandual 
tm_spr(void)325bdac52fSAnshuman Khandual void tm_spr(void)
335bdac52fSAnshuman Khandual {
345bdac52fSAnshuman Khandual 	unsigned long result, texasr;
355bdac52fSAnshuman Khandual 	int ret;
365bdac52fSAnshuman Khandual 
375bdac52fSAnshuman Khandual 	cptr = (struct shared *)shmat(shm_id, NULL, 0);
385bdac52fSAnshuman Khandual 	cptr1 = (int *)shmat(shm_id1, NULL, 0);
395bdac52fSAnshuman Khandual 
405bdac52fSAnshuman Khandual trans:
415bdac52fSAnshuman Khandual 	cptr1[0] = 0;
425bdac52fSAnshuman Khandual 	asm __volatile__(
435bdac52fSAnshuman Khandual 		"1: ;"
445bdac52fSAnshuman Khandual 		/* TM failover handler should follow "tbegin.;" */
455bdac52fSAnshuman Khandual 		"mflr 31;"
465bdac52fSAnshuman Khandual 		"bl 4f;"	/* $ = TFHAR - 12 */
475bdac52fSAnshuman Khandual 		"4: ;"
485bdac52fSAnshuman Khandual 		"mflr %[tfhar];"
495bdac52fSAnshuman Khandual 		"mtlr 31;"
505bdac52fSAnshuman Khandual 
515bdac52fSAnshuman Khandual 		"tbegin.;"
525bdac52fSAnshuman Khandual 		"beq 2f;"
535bdac52fSAnshuman Khandual 
545bdac52fSAnshuman Khandual 		"tsuspend.;"
555bdac52fSAnshuman Khandual 		"li 8, 1;"
565bdac52fSAnshuman Khandual 		"sth 8, 0(%[cptr1]);"
575bdac52fSAnshuman Khandual 		"tresume.;"
585bdac52fSAnshuman Khandual 		"b .;"
595bdac52fSAnshuman Khandual 
605bdac52fSAnshuman Khandual 		"tend.;"
615bdac52fSAnshuman Khandual 		"li 0, 0;"
625bdac52fSAnshuman Khandual 		"ori %[res], 0, 0;"
635bdac52fSAnshuman Khandual 		"b 3f;"
645bdac52fSAnshuman Khandual 
655bdac52fSAnshuman Khandual 		"2: ;"
665bdac52fSAnshuman Khandual 
675bdac52fSAnshuman Khandual 		"li 0, 1;"
685bdac52fSAnshuman Khandual 		"ori %[res], 0, 0;"
695bdac52fSAnshuman Khandual 		"mfspr %[texasr], %[sprn_texasr];"
705bdac52fSAnshuman Khandual 
715bdac52fSAnshuman Khandual 		"3: ;"
725bdac52fSAnshuman Khandual 		: [tfhar] "=r" (tfhar), [res] "=r" (result),
735249497aSBreno Leitao 		[texasr] "=r" (texasr), [cptr1] "=b" (cptr1)
745bdac52fSAnshuman Khandual 		: [sprn_texasr] "i"  (SPRN_TEXASR)
75f36dbfe1SSimon Guo 		: "memory", "r0", "r8", "r31"
765bdac52fSAnshuman Khandual 		);
775bdac52fSAnshuman Khandual 
785bdac52fSAnshuman Khandual 	/* There are 2 32bit instructions before tbegin. */
795bdac52fSAnshuman Khandual 	tfhar += 12;
805bdac52fSAnshuman Khandual 
815bdac52fSAnshuman Khandual 	if (result) {
825bdac52fSAnshuman Khandual 		if (!cptr->flag)
835bdac52fSAnshuman Khandual 			goto trans;
845bdac52fSAnshuman Khandual 
855bdac52fSAnshuman Khandual 		ret = validate_tm_spr((struct tm_spr_regs *)&cptr->regs);
865bdac52fSAnshuman Khandual 		shmdt((void *)cptr);
875bdac52fSAnshuman Khandual 		shmdt((void *)cptr1);
885bdac52fSAnshuman Khandual 		if (ret)
895bdac52fSAnshuman Khandual 			exit(1);
905bdac52fSAnshuman Khandual 		exit(0);
915bdac52fSAnshuman Khandual 	}
925bdac52fSAnshuman Khandual 	shmdt((void *)cptr);
935bdac52fSAnshuman Khandual 	shmdt((void *)cptr1);
945bdac52fSAnshuman Khandual 	exit(1);
955bdac52fSAnshuman Khandual }
965bdac52fSAnshuman Khandual 
trace_tm_spr(pid_t child)975bdac52fSAnshuman Khandual int trace_tm_spr(pid_t child)
985bdac52fSAnshuman Khandual {
995bdac52fSAnshuman Khandual 	FAIL_IF(start_trace(child));
1005bdac52fSAnshuman Khandual 	FAIL_IF(show_tm_spr(child, (struct tm_spr_regs *)&pptr->regs));
1015bdac52fSAnshuman Khandual 
1025bdac52fSAnshuman Khandual 	printf("TFHAR: %lx TEXASR: %lx TFIAR: %lx\n", pptr->regs.tm_tfhar,
1035bdac52fSAnshuman Khandual 				pptr->regs.tm_texasr, pptr->regs.tm_tfiar);
1045bdac52fSAnshuman Khandual 
1055bdac52fSAnshuman Khandual 	pptr->flag = 1;
1065bdac52fSAnshuman Khandual 	FAIL_IF(stop_trace(child));
1075bdac52fSAnshuman Khandual 
1085bdac52fSAnshuman Khandual 	return TEST_PASS;
1095bdac52fSAnshuman Khandual }
1105bdac52fSAnshuman Khandual 
ptrace_tm_spr(void)1115bdac52fSAnshuman Khandual int ptrace_tm_spr(void)
1125bdac52fSAnshuman Khandual {
1135bdac52fSAnshuman Khandual 	pid_t pid;
1145bdac52fSAnshuman Khandual 	int ret, status;
1155bdac52fSAnshuman Khandual 
116*68877ff2SBenjamin Gray 	SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
117*68877ff2SBenjamin Gray 	SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
1185bdac52fSAnshuman Khandual 	shm_id = shmget(IPC_PRIVATE, sizeof(struct shared), 0777|IPC_CREAT);
1195bdac52fSAnshuman Khandual 	shm_id1 = shmget(IPC_PRIVATE, sizeof(int), 0777|IPC_CREAT);
1205bdac52fSAnshuman Khandual 	pid = fork();
1215bdac52fSAnshuman Khandual 	if (pid < 0) {
1225bdac52fSAnshuman Khandual 		perror("fork() failed");
1235bdac52fSAnshuman Khandual 		return TEST_FAIL;
1245bdac52fSAnshuman Khandual 	}
1255bdac52fSAnshuman Khandual 
1265bdac52fSAnshuman Khandual 	if (pid == 0)
1275bdac52fSAnshuman Khandual 		tm_spr();
1285bdac52fSAnshuman Khandual 
1295bdac52fSAnshuman Khandual 	if (pid) {
1305bdac52fSAnshuman Khandual 		pptr = (struct shared *)shmat(shm_id, NULL, 0);
1315bdac52fSAnshuman Khandual 		pptr1 = (int *)shmat(shm_id1, NULL, 0);
1325bdac52fSAnshuman Khandual 
1335bdac52fSAnshuman Khandual 		while (!pptr1[0])
1345bdac52fSAnshuman Khandual 			asm volatile("" : : : "memory");
1355bdac52fSAnshuman Khandual 		ret = trace_tm_spr(pid);
1365bdac52fSAnshuman Khandual 		if (ret) {
1375bdac52fSAnshuman Khandual 			kill(pid, SIGKILL);
1385bdac52fSAnshuman Khandual 			shmdt((void *)pptr);
1395bdac52fSAnshuman Khandual 			shmdt((void *)pptr1);
1405bdac52fSAnshuman Khandual 			shmctl(shm_id, IPC_RMID, NULL);
1415bdac52fSAnshuman Khandual 			shmctl(shm_id1, IPC_RMID, NULL);
1425bdac52fSAnshuman Khandual 			return TEST_FAIL;
1435bdac52fSAnshuman Khandual 		}
1445bdac52fSAnshuman Khandual 
1455bdac52fSAnshuman Khandual 		shmdt((void *)pptr);
1465bdac52fSAnshuman Khandual 		shmdt((void *)pptr1);
1475bdac52fSAnshuman Khandual 		ret = wait(&status);
1485bdac52fSAnshuman Khandual 		shmctl(shm_id, IPC_RMID, NULL);
1495bdac52fSAnshuman Khandual 		shmctl(shm_id1, IPC_RMID, NULL);
1505bdac52fSAnshuman Khandual 		if (ret != pid) {
1515bdac52fSAnshuman Khandual 			printf("Child's exit status not captured\n");
1525bdac52fSAnshuman Khandual 			return TEST_FAIL;
1535bdac52fSAnshuman Khandual 		}
1545bdac52fSAnshuman Khandual 
1555bdac52fSAnshuman Khandual 		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
1565bdac52fSAnshuman Khandual 			TEST_PASS;
1575bdac52fSAnshuman Khandual 	}
1585bdac52fSAnshuman Khandual 	return TEST_PASS;
1595bdac52fSAnshuman Khandual }
1605bdac52fSAnshuman Khandual 
main(int argc,char * argv[])1615bdac52fSAnshuman Khandual int main(int argc, char *argv[])
1625bdac52fSAnshuman Khandual {
1635bdac52fSAnshuman Khandual 	return test_harness(ptrace_tm_spr, "ptrace_tm_spr");
1645bdac52fSAnshuman Khandual }
165