Home | History | Annotate | Download | only in ptrace
      1 /*
      2  * Ptrace test for GPR/FPR registers in TM context
      3  *
      4  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
      5  *
      6  * This program is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU General Public License
      8  * as published by the Free Software Foundation; either version
      9  * 2 of the License, or (at your option) any later version.
     10  */
     11 #include "ptrace.h"
     12 #include "ptrace-gpr.h"
     13 #include "tm.h"
     14 
     15 /* Tracer and Tracee Shared Data */
     16 int shm_id;
     17 unsigned long *cptr, *pptr;
     18 
     19 float a = FPR_1;
     20 float b = FPR_2;
     21 float c = FPR_3;
     22 
     23 void tm_gpr(void)
     24 {
     25 	unsigned long gpr_buf[18];
     26 	unsigned long result, texasr;
     27 	float fpr_buf[32];
     28 
     29 	printf("Starting the child\n");
     30 	cptr = (unsigned long *)shmat(shm_id, NULL, 0);
     31 
     32 trans:
     33 	cptr[1] = 0;
     34 	asm __volatile__(
     35 		ASM_LOAD_GPR_IMMED(gpr_1)
     36 		ASM_LOAD_FPR_SINGLE_PRECISION(flt_1)
     37 		"1: ;"
     38 		"tbegin.;"
     39 		"beq 2f;"
     40 		ASM_LOAD_GPR_IMMED(gpr_2)
     41 		ASM_LOAD_FPR_SINGLE_PRECISION(flt_2)
     42 		"tsuspend.;"
     43 		"li 7, 1;"
     44 		"stw 7, 0(%[cptr1]);"
     45 		"tresume.;"
     46 		"b .;"
     47 
     48 		"tend.;"
     49 		"li 0, 0;"
     50 		"ori %[res], 0, 0;"
     51 		"b 3f;"
     52 
     53 		/* Transaction abort handler */
     54 		"2: ;"
     55 		"li 0, 1;"
     56 		"ori %[res], 0, 0;"
     57 		"mfspr %[texasr], %[sprn_texasr];"
     58 
     59 		"3: ;"
     60 		: [res] "=r" (result), [texasr] "=r" (texasr)
     61 		: [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2),
     62 		[sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a),
     63 		[flt_2] "r" (&b), [cptr1] "r" (&cptr[1])
     64 		: "memory", "r7", "r8", "r9", "r10",
     65 		"r11", "r12", "r13", "r14", "r15", "r16",
     66 		"r17", "r18", "r19", "r20", "r21", "r22",
     67 		"r23", "r24", "r25", "r26", "r27", "r28",
     68 		"r29", "r30", "r31"
     69 		);
     70 
     71 	if (result) {
     72 		if (!cptr[0])
     73 			goto trans;
     74 
     75 		shmdt((void *)cptr);
     76 		store_gpr(gpr_buf);
     77 		store_fpr_single_precision(fpr_buf);
     78 
     79 		if (validate_gpr(gpr_buf, GPR_3))
     80 			exit(1);
     81 
     82 		if (validate_fpr_float(fpr_buf, c))
     83 			exit(1);
     84 
     85 		exit(0);
     86 	}
     87 	shmdt((void *)cptr);
     88 	exit(1);
     89 }
     90 
     91 int trace_tm_gpr(pid_t child)
     92 {
     93 	unsigned long gpr[18];
     94 	unsigned long fpr[32];
     95 
     96 	FAIL_IF(start_trace(child));
     97 	FAIL_IF(show_gpr(child, gpr));
     98 	FAIL_IF(validate_gpr(gpr, GPR_2));
     99 	FAIL_IF(show_fpr(child, fpr));
    100 	FAIL_IF(validate_fpr(fpr, FPR_2_REP));
    101 	FAIL_IF(show_ckpt_fpr(child, fpr));
    102 	FAIL_IF(validate_fpr(fpr, FPR_1_REP));
    103 	FAIL_IF(show_ckpt_gpr(child, gpr));
    104 	FAIL_IF(validate_gpr(gpr, GPR_1));
    105 	FAIL_IF(write_ckpt_gpr(child, GPR_3));
    106 	FAIL_IF(write_ckpt_fpr(child, FPR_3_REP));
    107 
    108 	pptr[0] = 1;
    109 	FAIL_IF(stop_trace(child));
    110 
    111 	return TEST_PASS;
    112 }
    113 
    114 int ptrace_tm_gpr(void)
    115 {
    116 	pid_t pid;
    117 	int ret, status;
    118 
    119 	SKIP_IF(!have_htm());
    120 	shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
    121 	pid = fork();
    122 	if (pid < 0) {
    123 		perror("fork() failed");
    124 		return TEST_FAIL;
    125 	}
    126 	if (pid == 0)
    127 		tm_gpr();
    128 
    129 	if (pid) {
    130 		pptr = (unsigned long *)shmat(shm_id, NULL, 0);
    131 
    132 		while (!pptr[1])
    133 			asm volatile("" : : : "memory");
    134 		ret = trace_tm_gpr(pid);
    135 		if (ret) {
    136 			kill(pid, SIGTERM);
    137 			return TEST_FAIL;
    138 		}
    139 
    140 		shmdt((void *)pptr);
    141 
    142 		ret = wait(&status);
    143 		shmctl(shm_id, IPC_RMID, NULL);
    144 		if (ret != pid) {
    145 			printf("Child's exit status not captured\n");
    146 			return TEST_FAIL;
    147 		}
    148 
    149 		return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
    150 			TEST_PASS;
    151 	}
    152 	return TEST_PASS;
    153 }
    154 
    155 int main(int argc, char *argv[])
    156 {
    157 	return test_harness(ptrace_tm_gpr, "ptrace_tm_gpr");
    158 }
    159