[PATCH 0/3] Add new ptrace request macros on PowerPC

Anshuman Khandual khandual at linux.vnet.ibm.com
Wed Apr 2 18:02:21 EST 2014


	This patch series adds new ELF note sections which are used to
create new ptrace request macros for various transactional memory and
miscellaneous registers on PowerPC. Please find the test case exploiting
the new ptrace request macros and it's results on a POWER8 system.

RFC: https://lkml.org/lkml/2014/4/1/292

============================== Results ==============================
-------TM specific SPR------
TM TFHAR: 100009dc
TM TEXASR: de000001ac000001
TM TFIAR: c00000000003f386
TM CH ORIG_MSR: 900000050000f032
TM CH TAR: 6
TM CH PPR: c000000000000
TM CH DSCR: 1
-------TM checkpointed GPR-----
TM CH GPR[0]: 1000097c
TM CH GPR[1]: 5
TM CH GPR[2]: 6
TM CH GPR[7]: 1
TM CH NIP: 100009dc
TM CH LINK: 1000097c
TM CH CCR: 22000422
-------TM running GPR-----
TM RN GPR[0]: 1000097c
TM RN GPR[1]: 7
TM RN GPR[2]: 8
TM RN GPR[7]: 5
TM RN NIP: 100009fc
TM RN LINK: 1000097c
TM RN CCR: 2000422
-------TM running FPR-----
TM RN FPR[0]: 1002d3a3780
TM RN FPR[1]: 7
TM RN FPR[2]: 8
TM RN FPSCR: 0
-------TM checkpointed FPR-----
TM CH FPR[0]: 1002d3a3780
TM CH FPR[1]: 5
TM CH FPR[2]: 6
TM CH FPSCR: 0
-------Running miscellaneous registers-------
TM RN DSCR: 0
TM RN PPR: c000000000000
TM RN TAR: 8
============================ Test case ==============================
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/user.h>
#include <linux/elf.h>
#include <linux/types.h>

typedef unsigned long u64;
typedef unsigned int u32;

typedef __vector128 vector128;

/* TM CFPR */
struct tm_cfpr {
	u64     fpr[32];
	u64     fpscr;
};

/* TM CVMX */
struct tm_cvmx {
        vector128       vr[32] __attribute__((aligned(16)));
        vector128       vscr __attribute__((aligned(16)));
	u32		vrsave;	
};

/* TM SPR */
struct tm_spr_regs {
	u64	tm_tfhar;
	u64	tm_texasr;
	u64	tm_tfiar;
	u64	tm_orig_msr;
	u64	tm_tar;
	u64	tm_ppr;
	u64	tm_dscr;
};

/* Miscellaneous registers */
struct misc_regs {
	u64	dscr;
	u64	ppr;
	u64	tar;
};

/* TM instructions */
#define TBEGIN          ".long 0x7C00051D ;"
#define TEND            ".long 0x7C00055D ;"

#define SPRN_DSCR	0x3
#define SPRN_TAR	815

/* Ptrace request macros */
#define PTRACE_GETTM_SPRREGS    0x70
#define PTRACE_SETTM_SPRREGS    0x71
#define PTRACE_GETTM_CGPRREGS   0x72
#define PTRACE_SETTM_CGPRREGS   0x73
#define PTRACE_GETTM_CFPRREGS   0x74
#define PTRACE_SETTM_CFPRREGS   0x75
#define PTRACE_GETTM_CVMXREG    0x76
#define PTRACE_SETTM_CVMXREG    0x77
#define PTRACE_GETMSCREGS	0x78
#define PTRACE_SETMSCREGS	0x79

int main(int argc, char *argv[])
{
	struct tm_spr_regs *tmr1;
	struct pt_regs *pregs1, *pregs2;
	struct tm_cfpr *fpr, *fpr1;
	struct tm_cvmx *vr1;
	struct misc_regs *dbr1;

	pid_t child;
	int ret = 0, status = 0, i = 0, flag = 1;

	tmr1 = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
	pregs1 = (struct pt_regs *) malloc(sizeof(struct pt_regs));
	pregs2 = (struct pt_regs *) malloc(sizeof(struct pt_regs));
	fpr = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
	fpr1 = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
	vr1 = (struct tm_cvmx *) malloc(sizeof(struct tm_cvmx));
	dbr1 = (struct misc_regs *) malloc(sizeof(struct misc_regs));

	child = fork();
	if (child < 0) {
		printf("fork() failed \n");
		exit(-1);
	}

	/* Child code */
	if (child == 0) {
		asm __volatile__(
			"6: ;"			/* TM checkpointed values */
			"li 1, 5;"		/* GPR[1] */
			".long 0x7C210166;"	/* FPR[1] */
			"li 2, 6;"		/* GPR[2] */
			".long 0x7C420166;"	/* FPR[2] */
			"mtspr %[tar], 2;"	/* TAR */
			"li 7, 1;"		/* GPR[7] */
 			"mtspr %[dscr], 7;"	/* DSCR */
			"1: ;"
			TBEGIN			/* TM running values */
			"beq 2f ;"
		 	"li 1, 7;"		/* GPR[1] */
                        ".long 0x7C210166;"	/* FPR[1] */
                        "li 2, 8;"		/* GPR[2] */
                        ".long 0x7C420166;"	/* FPR[2] */
                        "mtspr %[tar], 2;"	/* TAR */
                        "li 7, 5;"		/* GPR[7] */
			"mtspr %[dscr], 7;"	/* DSCR */
			"b .;"
			TEND
			"2: ;"			/* Abort handler */
			"b 1b;"			/* Start from TBEGIN */

			"3: ;"
			"b 6b;"			/* Start all over again */
			:: [dscr]"i"(SPRN_DSCR), [tar]"i"(SPRN_TAR)
			: "memory", "r7");
	}

	/* Parent */
	if (child) {
		do {
			/* Wait till child hits "b ." instruction */
			sleep(3);

			memset(tmr1, 0 , sizeof(struct tm_spr_regs));
			memset(pregs1, 0 , sizeof(struct pt_regs));
			memset(pregs2, 0 , sizeof(struct pt_regs));
			memset(fpr1, 0 , sizeof(struct tm_cfpr));
			memset(fpr, 0 , sizeof(struct tm_cfpr));
			memset(vr1, 0 , sizeof(struct tm_cvmx));
			memset(dbr1, 0 , sizeof(struct misc_regs));

			ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
			if (ret == -1) {
				printf("PTRACE_ATTACH failed: %s\n", strerror(errno));
				exit(-1);
			}

			ret = waitpid(child, NULL, 0);
			if (ret != child) {
				printf("PID does not match\n");
				exit(-1);
			}

			/* TM specific SPR */
			ret = ptrace(PTRACE_GETTM_SPRREGS, child, NULL, tmr1);
			if (ret == -1) {
				printf("PTRACE_GETTM_SPRREGS failed: %s\n", strerror(errno));
				exit(-1);
			}

			printf("-------TM specific SPR------\n");
			printf("TM TFHAR: %lx\n", tmr1->tm_tfhar);
			printf("TM TEXASR: %lx\n", tmr1->tm_texasr);
			printf("TM TFIAR: %lx\n", tmr1->tm_tfiar);
			printf("TM CH ORIG_MSR: %lx\n", tmr1->tm_orig_msr);
			printf("TM CH TAR: %lx\n", tmr1->tm_tar);
			printf("TM CH PPR: %lx\n", tmr1->tm_ppr);
			printf("TM CH DSCR: %lx\n", tmr1->tm_dscr);

			/* TM checkpointed GPR */
			ret = ptrace(PTRACE_GETTM_CGPRREGS, child, NULL, pregs1);
			if (ret == -1) {
				printf("PTRACE_GETTM_CGPRREGS failed: %s\n", strerror(errno));
				exit(-1);
			}

			printf("-------TM checkpointed GPR-----\n");
			printf("TM CH GPR[0]: %lx\n", pregs1->gpr[0]);
			printf("TM CH GPR[1]: %lx\n", pregs1->gpr[1]);
			printf("TM CH GPR[2]: %lx\n", pregs1->gpr[2]);
			printf("TM CH GPR[7]: %lx\n", pregs1->gpr[7]);
			printf("TM CH NIP: %lx\n", pregs1->nip);
			printf("TM CH LINK: %lx\n", pregs1->link);
			printf("TM CH CCR: %lx\n", pregs1->ccr);

			/* TM running GPR */
			ret = ptrace(PTRACE_GETREGS, child, NULL, pregs2);
			if (ret == -1) {
				printf("PTRACE_GETREGS failed: %s\n", strerror(errno));
				exit(-1);
			}

			printf("-------TM running GPR-----\n");
			printf("TM RN GPR[0]: %lx\n", pregs2->gpr[0]);
			printf("TM RN GPR[1]: %lx\n", pregs2->gpr[1]);
			printf("TM RN GPR[2]: %lx\n", pregs2->gpr[2]);
			printf("TM RN GPR[7]: %lx\n", pregs2->gpr[7]);
			printf("TM RN NIP: %lx\n", pregs2->nip);
			printf("TM RN LINK: %lx\n", pregs2->link);
			printf("TM RN CCR: %lx\n", pregs2->ccr);

			/* TM running FPR */
			ret = ptrace(PTRACE_GETFPREGS, child, NULL, fpr);
			if (ret == -1) {
				printf("PTRACE_GETFPREGS failed: %s\n", strerror(errno));
				exit(-1);
			}

			printf("-------TM running FPR-----\n");
			printf("TM RN FPR[0]: %lx\n", fpr->fpr[0]);
			printf("TM RN FPR[1]: %lx\n", fpr->fpr[1]);
			printf("TM RN FPR[2]: %lx\n", fpr->fpr[2]);
			printf("TM RN FPSCR: %lx\n", fpr->fpscr);

			/* TM checkpointed FPR */
			ret = ptrace(PTRACE_GETTM_CFPRREGS, child, NULL, fpr1);
			if (ret == -1) {
				printf("PTRACE_GETTM_CFPRREGS failed: %s\n", strerror(errno));
				exit(-1);
			}
			printf("-------TM checkpointed FPR-----\n");
			printf("TM CH FPR[0]: %lx\n", fpr1->fpr[0]);
			printf("TM CH FPR[1]: %lx\n", fpr1->fpr[1]);
			printf("TM CH FPR[2]: %lx\n", fpr1->fpr[2]);
			printf("TM CH FPSCR: %lx\n", fpr1->fpscr);

			/* Misc debug */
			ret = ptrace(PTRACE_GETMSCREGS, child, NULL, dbr1);
			if (ret == -1) {
				printf("PTRACE_GETMSCREGS failed: %s\n", strerror(errno));
				exit(-1);
			}

			printf("-------Running miscellaneous registers-------\n");
			printf("TM RN DSCR: %lx\n", dbr1->dscr);
			printf("TM RN PPR: %lx\n", dbr1->ppr);
			printf("TM RN TAR: %lx\n", dbr1->tar);
	
			ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
			if (ret == -1) {
				printf("PTRACE_DETACH failed: %s\n", strerror(errno));
				exit(-1);
			}
		} while (0);
	}
	return 0;
}
=====================================================================

Anshuman Khandual (3):
  elf: Add some new PowerPC specifc note sections
  powerpc, ptrace: Add new ptrace request macros for transactional memory
  powerpc, ptrace: Add new ptrace request macro for miscellaneous registers

 arch/powerpc/include/asm/switch_to.h   |   8 +
 arch/powerpc/include/uapi/asm/ptrace.h |  61 +++
 arch/powerpc/kernel/process.c          |  24 ++
 arch/powerpc/kernel/ptrace.c           | 659 +++++++++++++++++++++++++++++++--
 include/uapi/linux/elf.h               |   5 +
 5 files changed, 729 insertions(+), 28 deletions(-)

-- 
1.7.11.7



More information about the Linuxppc-dev mailing list