All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-02  7:02 ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: avagin, oleg, roland, mikey, benh, Anshuman Khandual

	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


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-02  7:02 ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, avagin, oleg, roland, Anshuman Khandual

	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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/3] elf: Add some new PowerPC specifc note sections
  2014-04-02  7:02 ` Anshuman Khandual
@ 2014-04-02  7:02   ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: avagin, oleg, roland, mikey, benh, Anshuman Khandual

This patch adds four new note sections for transactional memory
and one note section for some miscellaneous registers. This addition
of new elf note sections extends the existing elf ABI without affecting
it in any manner.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 include/uapi/linux/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index ef6103b..bd59452 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -379,6 +379,11 @@ typedef struct elf64_shdr {
 #define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
 #define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
 #define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_PPC_TM_SPR	0x103		/* PowerPC transactional memory special registers */
+#define NT_PPC_TM_CGPR	0x104		/* PowerpC transactional memory checkpointed GPR */
+#define NT_PPC_TM_CFPR	0x105		/* PowerPC transactional memory checkpointed FPR */
+#define NT_PPC_TM_CVMX	0x106		/* PowerPC transactional memory checkpointed VMX */
+#define NT_PPC_MISC	0x107		/* PowerPC miscellaneous registers */
 #define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
 #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 1/3] elf: Add some new PowerPC specifc note sections
@ 2014-04-02  7:02   ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, avagin, oleg, roland, Anshuman Khandual

This patch adds four new note sections for transactional memory
and one note section for some miscellaneous registers. This addition
of new elf note sections extends the existing elf ABI without affecting
it in any manner.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 include/uapi/linux/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index ef6103b..bd59452 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -379,6 +379,11 @@ typedef struct elf64_shdr {
 #define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
 #define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
 #define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_PPC_TM_SPR	0x103		/* PowerPC transactional memory special registers */
+#define NT_PPC_TM_CGPR	0x104		/* PowerpC transactional memory checkpointed GPR */
+#define NT_PPC_TM_CFPR	0x105		/* PowerPC transactional memory checkpointed FPR */
+#define NT_PPC_TM_CVMX	0x106		/* PowerPC transactional memory checkpointed VMX */
+#define NT_PPC_MISC	0x107		/* PowerPC miscellaneous registers */
 #define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
 #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
  2014-04-02  7:02 ` Anshuman Khandual
@ 2014-04-02  7:02   ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: avagin, oleg, roland, mikey, benh, Anshuman Khandual

This patch adds following new sets of ptrace request macros for transactional
memory expanding the existing ptrace ABI on PowerPC.

	/* TM special purpose registers */
	PTRACE_GETTM_SPRREGS
	PTRACE_SETTM_SPRREGS

	/* TM checkpointed GPR registers */
	PTRACE_GETTM_CGPRREGS
	PTRACE_SETTM_CGPRREGS

	/* TM checkpointed FPR registers */
	PTRACE_GETTM_CFPRREGS
	PTRACE_SETTM_CFPRREGS

	/* TM checkpointed VMX registers */
	PTRACE_GETTM_CVMXREGS
	PTRACE_SETTM_CVMXREGS

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/switch_to.h   |   8 +
 arch/powerpc/include/uapi/asm/ptrace.h |  51 +++
 arch/powerpc/kernel/process.c          |  24 ++
 arch/powerpc/kernel/ptrace.c           | 570 +++++++++++++++++++++++++++++++--
 4 files changed, 625 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 0e83e7d..22095e2 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -80,6 +80,14 @@ static inline void flush_spe_to_thread(struct task_struct *t)
 }
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+extern void flush_tmreg_to_thread(struct task_struct *);
+#else
+static inline void flush_tmreg_to_thread(struct task_struct *t)
+{
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
 static inline void clear_task_ebb(struct task_struct *t)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h
index 77d2ed3..1a12c36 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -190,6 +190,57 @@ struct pt_regs {
 #define PPC_PTRACE_SETHWDEBUG	0x88
 #define PPC_PTRACE_DELHWDEBUG	0x87
 
+/* Transactional memory */
+
+/*
+ * TM specific SPR
+ *
+ * struct data {
+ * 	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long   tm_orig_msr;
+ *	u64		tm_tar;
+ *	u64		tm_ppr;
+ *	u64		tm_dscr;
+ * };
+ */
+#define PTRACE_GETTM_SPRREGS	0x70
+#define PTRACE_SETTM_SPRREGS	0x71
+
+/*
+ * TM Checkpointed GPR
+ *
+ * struct data {
+ *	struct pt_regs	ckpt_regs;
+ * };
+ */
+#define PTRACE_GETTM_CGPRREGS	0x72
+#define PTRACE_SETTM_CGPRREGS	0x73
+
+/*
+ * TM Checkpointed FPR
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
+#define PTRACE_GETTM_CFPRREGS	0x74
+#define PTRACE_SETTM_CFPRREGS	0x75
+
+/*
+ * TM Checkpointed VMX
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	unsigned long	vrsave;
+ *};
+ */
+#define PTRACE_GETTM_CVMXREGS	0x76
+#define PTRACE_SETTM_CVMXREGS	0x77
+
 #ifndef __ASSEMBLY__
 
 struct ppc_debug_info {
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index af064d2..230a0ee 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -673,6 +673,30 @@ static inline void __switch_to_tm(struct task_struct *prev)
 	}
 }
 
+void flush_tmreg_to_thread(struct task_struct *tsk)
+{
+	/*
+ 	 * If task is not current, it should have been flushed
+ 	 * already to it's thread_struct during __switch_to().
+ 	 */
+	if (tsk != current)
+		return;
+
+	preempt_disable();
+	if (tsk->thread.regs) {
+		/*
+ 		 * If we are still current, the TM state need to
+ 		 * be flushed to thread_struct as it will be still
+ 		 * present in the current cpu
+ 		 */
+		if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+			__switch_to_tm(tsk);
+			tm_recheckpoint_new_task(tsk);
+		}
+	}
+	preempt_enable();
+}
+
 /*
  * This is called if we are on the way out to userspace and the
  * TIF_RESTORE_TM flag is set.  It checks if we need to reload
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 2e3d2bf..9fbcb6a 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -357,6 +357,17 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+/*
+ * When any transaction is active, "thread_struct->transact_fp" holds
+ * the current running value of all FPR registers and "thread_struct->
+ * fp_state" holds the last checkpointed FPR registers state for the
+ * current transaction.
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
@@ -365,21 +376,41 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 	u64 buf[33];
 	int i;
 #endif
-	flush_fp_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_fp_to_thread(target);
+	}
 
 #ifdef CONFIG_VSX
 	/* copy to local buffer then write that out */
-	for (i = 0; i < 32 ; i++)
-		buf[i] = target->thread.TS_FPR(i);
-	buf[32] = target->thread.fp_state.fpscr;
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_TRANS_FPR(i);
+		buf[32] = target->thread.transact_fp.fpscr;
+	} else {
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_FPR(i);
+		buf[32] = target->thread.fp_state.fpscr;
+	}
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 
 #else
-	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+	if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+		BUILD_BUG_ON(offsetof(struct transact_fp, fpscr) !=
+				offsetof(struct transact_fp, fpr[32][0]));
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   &target->thread.transact_fp, 0, -1);
+	} esle {
+		BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+			     offsetof(struct thread_fp_state, fpr[32][0]));
+
+		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
+	}
 #endif
 }
 
@@ -391,23 +422,44 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 	u64 buf[33];
 	int i;
 #endif
-	flush_fp_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_fp_to_thread(target);
+	}
 
 #ifdef CONFIG_VSX
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
 		return i;
-	for (i = 0; i < 32 ; i++)
-		target->thread.TS_FPR(i) = buf[i];
-	target->thread.fp_state.fpscr = buf[32];
+	for (i = 0; i < 32 ; i++) {
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			target->thread.TS_TRANS_FPR(i) = buf[i];
+		else
+			target->thread.TS_FPR(i) = buf[i];
+	}
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		target->thread.transact_fp.fpscr = buf[32];
+	else
+		target->thread.fp_state.fpscr = buf[32];
 	return 0;
 #else
-	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		BUILD_BUG_ON(offsetof(struct transact_fp, fpscr) !=
+			     offsetof(struct transact_fp, fpr[32][0]));
 
-	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fp_state, 0, -1);
+		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.transact_fp, 0, -1);
+	} else {
+		BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+			     offsetof(struct thread_fp_state, fpr[32][0]));
+
+		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.fp_state, 0, -1);
+	}
 #endif
 }
 
@@ -432,20 +484,44 @@ static int vr_active(struct task_struct *target,
 	return target->thread.used_vr ? regset->n : 0;
 }
 
+/*
+ * When any transaction is active, "thread_struct->transact_vr" holds
+ * the current running value of all VMX registers and "thread_struct->
+ * vr_state" holds the last checkpointed value of VMX registers for the
+ * current transaction.
+ *
+ * struct data {
+ * 	vector128	vr[32];
+ * 	vector128	vscr;
+ * 	vector128	vrsave;
+ * };
+ */
 static int vr_get(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  void *kbuf, void __user *ubuf)
 {
 	int ret;
+	struct thread_vr_state *addr;
 
-	flush_altivec_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_altivec_to_thread(target);
+	}
 
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		addr = &target->thread.transact_vr;
+	else
+		addr = &target->thread.vr_state;
+
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.vr_state, 0,
-				  33 * sizeof(vector128));
+				addr, 0, 33 * sizeof(vector128));
+
 	if (!ret) {
 		/*
 		 * Copy out only the low-order word of vrsave.
@@ -455,11 +531,14 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
-		vrsave.word = target->thread.vrsave;
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+
 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
 					  33 * sizeof(vector128), -1);
 	}
-
 	return ret;
 }
 
@@ -467,16 +546,27 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  const void *kbuf, const void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
-	flush_altivec_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_altivec_to_thread(target);
+	}
 
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		addr = &target->thread.transact_vr;
+	else
+		addr = &target->thread.vr_state;
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &target->thread.vr_state, 0,
-				 33 * sizeof(vector128));
+			addr, 0, 33 * sizeof(vector128));
+
 	if (!ret && count > 0) {
 		/*
 		 * We use only the first word of vrsave.
@@ -486,13 +576,21 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
-		vrsave.word = target->thread.vrsave;
+
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
 					 33 * sizeof(vector128), -1);
-		if (!ret)
-			target->thread.vrsave = vrsave.word;
+		if (!ret) {
+			if (MSR_TM_ACTIVE(target->thread.regs->msr))
+				target->thread.transact_vrsave = vrsave.word;
+			else
+				target->thread.vrsave = vrsave.word;
+		}
 	}
-
 	return ret;
 }
 #endif /* CONFIG_ALTIVEC */
@@ -613,6 +711,347 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset,
 }
 #endif /* CONFIG_SPE */
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+
+/*
+ *  Transactional memory SPR
+ *
+ * struct {
+ * 	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ * 	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfhar) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_texasr));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_texasr, sizeof(u64), 2 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_texasr) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_tfiar));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfiar, 2 * sizeof(u64), 3 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfiar) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_orig_msr));
+
+	/* TM checkpointed original MSR */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_orig_msr) +
+			sizeof(unsigned long) + sizeof(struct pt_regs)
+				!= offsetof(struct thread_struct, tm_tar));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long) , 3 * sizeof(u64) +
+					2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tar)
+			+ sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_ppr));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+					2 * sizeof(unsigned long), 3 * sizeof(u64) +
+						3 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_ppr) +
+			sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_dscr));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_dscr, 3 * sizeof(u64)
+				+ 3 * sizeof(unsigned long), 3 * sizeof(u64)
+						+ 4 * sizeof(unsigned long));
+	return ret;
+}
+
+static int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfhar)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_texasr));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_texasr, sizeof(u64), 2 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_texasr)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_tfiar));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfiar, 2 * sizeof(u64), 3 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfiar)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_orig_msr));
+
+	/* TM checkpointed orig MSR */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_orig_msr)
+		+ sizeof(unsigned long) + sizeof(struct pt_regs) !=
+			offsetof(struct thread_struct, tm_tar));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long), 3 * sizeof(u64) +
+					2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tar)
+			+ sizeof(unsigned long) != offsetof(struct thread_struct, tm_ppr));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64)
+					+ 2 * sizeof(unsigned long), 3 * sizeof(u64)
+					+ 3 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_ppr) +
+			sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_dscr));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr,
+					3 * sizeof(u64) + 3 * sizeof(unsigned long),
+					3 * sizeof(u64) + 4 * sizeof(unsigned long));
+
+	return ret;
+}
+
+/*
+ * TM Checkpointed GPR
+ *
+ * struct data {
+ * 	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.ckpt_regs, 0,
+				sizeof(struct pt_regs));
+	return ret;
+}
+
+static int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+						sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * TM Checkpointed FPR
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
+static int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+#ifdef CONFIG_VSX
+	u64 buf[33];
+	int i;
+#endif
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+#ifdef CONFIG_VSX
+	/* copy to local buffer then write that out */
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.TS_FPR(i);
+	buf[32] = target->thread.fp_state.fpscr;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+
+#else
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		offsetof(struct thread_fp_state, fpr[32][0]));
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.thread_fp_state, 0, -1);
+#endif
+}
+
+static int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+#ifdef CONFIG_VSX
+	u64 buf[33];
+	int i;
+#endif
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+#ifdef CONFIG_VSX
+	/* copy to local buffer then write that out */
+	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+	if (i)
+		return i;
+	for (i = 0; i < 32 ; i++)
+		target->thread.TS_FPR(i) = buf[i];
+	target->thread.fp_state.fpscr = buf[32];
+        return 0;
+#else
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		      offsetof(struct thread_fp_state, fpr[32][0]));
+
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.fp_state, 0, -1);
+#endif
+}
+
+/*
+ * TM Checkpointed VMX
+ *
+ * struct data {
+ * 	vector128	vr[32];
+ * 	vector128	vscr;
+ * 	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		     offsetof(struct thread_vr_state, vr[32]));
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &target->thread.vr_state, 0,
+				  33 * sizeof(vector128));
+	if (!ret) {
+		/*
+		 * Copy out only the low-order word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+					  33 * sizeof(vector128), -1);
+	}
+	return ret;
+}
+
+static int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		offsetof(struct thread_vr_state, vr[32]));
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &target->thread.vr_state, 0,
+				 33 * sizeof(vector128));
+	if (!ret && count > 0) {
+		/*
+		 * We use only the first word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+					 33 * sizeof(vector128), -1);
+		if (!ret)
+			target->thread.vrsave = vrsave.word;
+	}
+	return ret;
+}
+#endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
  * These are our native regset flavors.
@@ -629,6 +1068,12 @@ enum powerpc_regset {
 #ifdef CONFIG_SPE
 	REGSET_SPE,
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	REGSET_TM_SPR,		/* TM specific SPR */
+	REGSET_TM_CGPR,		/* TM checkpointed GPR */
+	REGSET_TM_CFPR,		/* TM checkpointed FPR */
+	REGSET_TM_CVMX		/* TM checkpointed VMX */
+#endif
 };
 
 static const struct user_regset native_regsets[] = {
@@ -663,6 +1108,28 @@ static const struct user_regset native_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = 7,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = 14,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_cgpr_get, .set = tm_cgpr_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = 34,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -831,6 +1298,28 @@ static const struct user_regset compat_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = 7,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = 14,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_cgpr_get, .set = tm_cgpr_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = 34,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
@@ -1754,7 +2243,32 @@ long arch_ptrace(struct task_struct *child, long request,
 					     REGSET_SPE, 0, 35 * sizeof(u32),
 					     datavp);
 #endif
-
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	case PTRACE_GETTM_SPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_SPR, 0, 6 * sizeof(u64) + sizeof(unsigned long), datavp);
+	case PTRACE_SETTM_SPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_SPR, 0, 6 * sizeof(u64) + sizeof(unsigned long), datavp);
+	case PTRACE_GETTM_CGPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CGPR, 0, sizeof(struct pt_regs), datavp);
+	case PTRACE_SETTM_CGPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CGPR, 0, sizeof(struct pt_regs), datavp);
+	case PTRACE_GETTM_CFPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CFPR, 0, sizeof(elf_fpregset_t), datavp);
+	case PTRACE_SETTM_CFPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CFPR, 0, sizeof(elf_fpregset_t), datavp);
+	case PTRACE_GETTM_CVMXREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
+	case PTRACE_SETTM_CVMXREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
@ 2014-04-02  7:02   ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, avagin, oleg, roland, Anshuman Khandual

This patch adds following new sets of ptrace request macros for transactional
memory expanding the existing ptrace ABI on PowerPC.

	/* TM special purpose registers */
	PTRACE_GETTM_SPRREGS
	PTRACE_SETTM_SPRREGS

	/* TM checkpointed GPR registers */
	PTRACE_GETTM_CGPRREGS
	PTRACE_SETTM_CGPRREGS

	/* TM checkpointed FPR registers */
	PTRACE_GETTM_CFPRREGS
	PTRACE_SETTM_CFPRREGS

	/* TM checkpointed VMX registers */
	PTRACE_GETTM_CVMXREGS
	PTRACE_SETTM_CVMXREGS

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/switch_to.h   |   8 +
 arch/powerpc/include/uapi/asm/ptrace.h |  51 +++
 arch/powerpc/kernel/process.c          |  24 ++
 arch/powerpc/kernel/ptrace.c           | 570 +++++++++++++++++++++++++++++++--
 4 files changed, 625 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 0e83e7d..22095e2 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -80,6 +80,14 @@ static inline void flush_spe_to_thread(struct task_struct *t)
 }
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+extern void flush_tmreg_to_thread(struct task_struct *);
+#else
+static inline void flush_tmreg_to_thread(struct task_struct *t)
+{
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
 static inline void clear_task_ebb(struct task_struct *t)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h
index 77d2ed3..1a12c36 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -190,6 +190,57 @@ struct pt_regs {
 #define PPC_PTRACE_SETHWDEBUG	0x88
 #define PPC_PTRACE_DELHWDEBUG	0x87
 
+/* Transactional memory */
+
+/*
+ * TM specific SPR
+ *
+ * struct data {
+ * 	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long   tm_orig_msr;
+ *	u64		tm_tar;
+ *	u64		tm_ppr;
+ *	u64		tm_dscr;
+ * };
+ */
+#define PTRACE_GETTM_SPRREGS	0x70
+#define PTRACE_SETTM_SPRREGS	0x71
+
+/*
+ * TM Checkpointed GPR
+ *
+ * struct data {
+ *	struct pt_regs	ckpt_regs;
+ * };
+ */
+#define PTRACE_GETTM_CGPRREGS	0x72
+#define PTRACE_SETTM_CGPRREGS	0x73
+
+/*
+ * TM Checkpointed FPR
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
+#define PTRACE_GETTM_CFPRREGS	0x74
+#define PTRACE_SETTM_CFPRREGS	0x75
+
+/*
+ * TM Checkpointed VMX
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	unsigned long	vrsave;
+ *};
+ */
+#define PTRACE_GETTM_CVMXREGS	0x76
+#define PTRACE_SETTM_CVMXREGS	0x77
+
 #ifndef __ASSEMBLY__
 
 struct ppc_debug_info {
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index af064d2..230a0ee 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -673,6 +673,30 @@ static inline void __switch_to_tm(struct task_struct *prev)
 	}
 }
 
+void flush_tmreg_to_thread(struct task_struct *tsk)
+{
+	/*
+ 	 * If task is not current, it should have been flushed
+ 	 * already to it's thread_struct during __switch_to().
+ 	 */
+	if (tsk != current)
+		return;
+
+	preempt_disable();
+	if (tsk->thread.regs) {
+		/*
+ 		 * If we are still current, the TM state need to
+ 		 * be flushed to thread_struct as it will be still
+ 		 * present in the current cpu
+ 		 */
+		if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+			__switch_to_tm(tsk);
+			tm_recheckpoint_new_task(tsk);
+		}
+	}
+	preempt_enable();
+}
+
 /*
  * This is called if we are on the way out to userspace and the
  * TIF_RESTORE_TM flag is set.  It checks if we need to reload
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 2e3d2bf..9fbcb6a 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -357,6 +357,17 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+/*
+ * When any transaction is active, "thread_struct->transact_fp" holds
+ * the current running value of all FPR registers and "thread_struct->
+ * fp_state" holds the last checkpointed FPR registers state for the
+ * current transaction.
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
@@ -365,21 +376,41 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 	u64 buf[33];
 	int i;
 #endif
-	flush_fp_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_fp_to_thread(target);
+	}
 
 #ifdef CONFIG_VSX
 	/* copy to local buffer then write that out */
-	for (i = 0; i < 32 ; i++)
-		buf[i] = target->thread.TS_FPR(i);
-	buf[32] = target->thread.fp_state.fpscr;
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_TRANS_FPR(i);
+		buf[32] = target->thread.transact_fp.fpscr;
+	} else {
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_FPR(i);
+		buf[32] = target->thread.fp_state.fpscr;
+	}
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 
 #else
-	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+	if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+		BUILD_BUG_ON(offsetof(struct transact_fp, fpscr) !=
+				offsetof(struct transact_fp, fpr[32][0]));
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   &target->thread.transact_fp, 0, -1);
+	} esle {
+		BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+			     offsetof(struct thread_fp_state, fpr[32][0]));
+
+		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
+	}
 #endif
 }
 
@@ -391,23 +422,44 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 	u64 buf[33];
 	int i;
 #endif
-	flush_fp_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_fp_to_thread(target);
+	}
 
 #ifdef CONFIG_VSX
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
 		return i;
-	for (i = 0; i < 32 ; i++)
-		target->thread.TS_FPR(i) = buf[i];
-	target->thread.fp_state.fpscr = buf[32];
+	for (i = 0; i < 32 ; i++) {
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			target->thread.TS_TRANS_FPR(i) = buf[i];
+		else
+			target->thread.TS_FPR(i) = buf[i];
+	}
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		target->thread.transact_fp.fpscr = buf[32];
+	else
+		target->thread.fp_state.fpscr = buf[32];
 	return 0;
 #else
-	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		BUILD_BUG_ON(offsetof(struct transact_fp, fpscr) !=
+			     offsetof(struct transact_fp, fpr[32][0]));
 
-	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fp_state, 0, -1);
+		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.transact_fp, 0, -1);
+	} else {
+		BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+			     offsetof(struct thread_fp_state, fpr[32][0]));
+
+		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.fp_state, 0, -1);
+	}
 #endif
 }
 
@@ -432,20 +484,44 @@ static int vr_active(struct task_struct *target,
 	return target->thread.used_vr ? regset->n : 0;
 }
 
+/*
+ * When any transaction is active, "thread_struct->transact_vr" holds
+ * the current running value of all VMX registers and "thread_struct->
+ * vr_state" holds the last checkpointed value of VMX registers for the
+ * current transaction.
+ *
+ * struct data {
+ * 	vector128	vr[32];
+ * 	vector128	vscr;
+ * 	vector128	vrsave;
+ * };
+ */
 static int vr_get(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  void *kbuf, void __user *ubuf)
 {
 	int ret;
+	struct thread_vr_state *addr;
 
-	flush_altivec_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_altivec_to_thread(target);
+	}
 
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		addr = &target->thread.transact_vr;
+	else
+		addr = &target->thread.vr_state;
+
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.vr_state, 0,
-				  33 * sizeof(vector128));
+				addr, 0, 33 * sizeof(vector128));
+
 	if (!ret) {
 		/*
 		 * Copy out only the low-order word of vrsave.
@@ -455,11 +531,14 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
-		vrsave.word = target->thread.vrsave;
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+
 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
 					  33 * sizeof(vector128), -1);
 	}
-
 	return ret;
 }
 
@@ -467,16 +546,27 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  const void *kbuf, const void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
-	flush_altivec_to_thread(target);
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_altivec_to_thread(target);
+		flush_tmreg_to_thread(target);
+	} else {
+		flush_altivec_to_thread(target);
+	}
 
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+	if (MSR_TM_ACTIVE(target->thread.regs->msr))
+		addr = &target->thread.transact_vr;
+	else
+		addr = &target->thread.vr_state;
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &target->thread.vr_state, 0,
-				 33 * sizeof(vector128));
+			addr, 0, 33 * sizeof(vector128));
+
 	if (!ret && count > 0) {
 		/*
 		 * We use only the first word of vrsave.
@@ -486,13 +576,21 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
-		vrsave.word = target->thread.vrsave;
+
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
 					 33 * sizeof(vector128), -1);
-		if (!ret)
-			target->thread.vrsave = vrsave.word;
+		if (!ret) {
+			if (MSR_TM_ACTIVE(target->thread.regs->msr))
+				target->thread.transact_vrsave = vrsave.word;
+			else
+				target->thread.vrsave = vrsave.word;
+		}
 	}
-
 	return ret;
 }
 #endif /* CONFIG_ALTIVEC */
@@ -613,6 +711,347 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset,
 }
 #endif /* CONFIG_SPE */
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+
+/*
+ *  Transactional memory SPR
+ *
+ * struct {
+ * 	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ * 	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfhar) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_texasr));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_texasr, sizeof(u64), 2 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_texasr) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_tfiar));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfiar, 2 * sizeof(u64), 3 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfiar) +
+			sizeof(u64) != offsetof(struct thread_struct, tm_orig_msr));
+
+	/* TM checkpointed original MSR */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_orig_msr) +
+			sizeof(unsigned long) + sizeof(struct pt_regs)
+				!= offsetof(struct thread_struct, tm_tar));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long) , 3 * sizeof(u64) +
+					2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tar)
+			+ sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_ppr));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+					2 * sizeof(unsigned long), 3 * sizeof(u64) +
+						3 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_ppr) +
+			sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_dscr));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_dscr, 3 * sizeof(u64)
+				+ 3 * sizeof(unsigned long), 3 * sizeof(u64)
+						+ 4 * sizeof(unsigned long));
+	return ret;
+}
+
+static int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfhar)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_texasr));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_texasr, sizeof(u64), 2 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_texasr)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_tfiar));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tfiar, 2 * sizeof(u64), 3 * sizeof(u64));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tfiar)
+		+ sizeof(u64) != offsetof(struct thread_struct, tm_orig_msr));
+
+	/* TM checkpointed orig MSR */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_orig_msr)
+		+ sizeof(unsigned long) + sizeof(struct pt_regs) !=
+			offsetof(struct thread_struct, tm_tar));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+			&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long), 3 * sizeof(u64) +
+					2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_tar)
+			+ sizeof(unsigned long) != offsetof(struct thread_struct, tm_ppr));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64)
+					+ 2 * sizeof(unsigned long), 3 * sizeof(u64)
+					+ 3 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, tm_ppr) +
+			sizeof(unsigned long) !=
+				offsetof(struct thread_struct, tm_dscr));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr,
+					3 * sizeof(u64) + 3 * sizeof(unsigned long),
+					3 * sizeof(u64) + 4 * sizeof(unsigned long));
+
+	return ret;
+}
+
+/*
+ * TM Checkpointed GPR
+ *
+ * struct data {
+ * 	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.ckpt_regs, 0,
+				sizeof(struct pt_regs));
+	return ret;
+}
+
+static int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+						sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * TM Checkpointed FPR
+ *
+ * struct data {
+ * 	u64	fpr[32];
+ * 	u64	fpscr;
+ * };
+ */
+static int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+#ifdef CONFIG_VSX
+	u64 buf[33];
+	int i;
+#endif
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+#ifdef CONFIG_VSX
+	/* copy to local buffer then write that out */
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.TS_FPR(i);
+	buf[32] = target->thread.fp_state.fpscr;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+
+#else
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		offsetof(struct thread_fp_state, fpr[32][0]));
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			&target->thread.thread_fp_state, 0, -1);
+#endif
+}
+
+static int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+#ifdef CONFIG_VSX
+	u64 buf[33];
+	int i;
+#endif
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+#ifdef CONFIG_VSX
+	/* copy to local buffer then write that out */
+	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+	if (i)
+		return i;
+	for (i = 0; i < 32 ; i++)
+		target->thread.TS_FPR(i) = buf[i];
+	target->thread.fp_state.fpscr = buf[32];
+        return 0;
+#else
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		      offsetof(struct thread_fp_state, fpr[32][0]));
+
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.fp_state, 0, -1);
+#endif
+}
+
+/*
+ * TM Checkpointed VMX
+ *
+ * struct data {
+ * 	vector128	vr[32];
+ * 	vector128	vscr;
+ * 	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		     offsetof(struct thread_vr_state, vr[32]));
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  &target->thread.vr_state, 0,
+				  33 * sizeof(vector128));
+	if (!ret) {
+		/*
+		 * Copy out only the low-order word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+					  33 * sizeof(vector128), -1);
+	}
+	return ret;
+}
+
+static int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmreg_to_thread(target);
+
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		offsetof(struct thread_vr_state, vr[32]));
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &target->thread.vr_state, 0,
+				 33 * sizeof(vector128));
+	if (!ret && count > 0) {
+		/*
+		 * We use only the first word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+					 33 * sizeof(vector128), -1);
+		if (!ret)
+			target->thread.vrsave = vrsave.word;
+	}
+	return ret;
+}
+#endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
  * These are our native regset flavors.
@@ -629,6 +1068,12 @@ enum powerpc_regset {
 #ifdef CONFIG_SPE
 	REGSET_SPE,
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	REGSET_TM_SPR,		/* TM specific SPR */
+	REGSET_TM_CGPR,		/* TM checkpointed GPR */
+	REGSET_TM_CFPR,		/* TM checkpointed FPR */
+	REGSET_TM_CVMX		/* TM checkpointed VMX */
+#endif
 };
 
 static const struct user_regset native_regsets[] = {
@@ -663,6 +1108,28 @@ static const struct user_regset native_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = 7,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = 14,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_cgpr_get, .set = tm_cgpr_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = 34,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -831,6 +1298,28 @@ static const struct user_regset compat_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = 7,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = 14,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = tm_cgpr_get, .set = tm_cgpr_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = 34,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
@@ -1754,7 +2243,32 @@ long arch_ptrace(struct task_struct *child, long request,
 					     REGSET_SPE, 0, 35 * sizeof(u32),
 					     datavp);
 #endif
-
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	case PTRACE_GETTM_SPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_SPR, 0, 6 * sizeof(u64) + sizeof(unsigned long), datavp);
+	case PTRACE_SETTM_SPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_SPR, 0, 6 * sizeof(u64) + sizeof(unsigned long), datavp);
+	case PTRACE_GETTM_CGPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CGPR, 0, sizeof(struct pt_regs), datavp);
+	case PTRACE_SETTM_CGPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CGPR, 0, sizeof(struct pt_regs), datavp);
+	case PTRACE_GETTM_CFPRREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CFPR, 0, sizeof(elf_fpregset_t), datavp);
+	case PTRACE_SETTM_CFPRREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CFPR, 0, sizeof(elf_fpregset_t), datavp);
+	case PTRACE_GETTM_CVMXREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
+	case PTRACE_SETTM_CVMXREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/3] powerpc, ptrace: Add new ptrace request macro for miscellaneous registers
  2014-04-02  7:02 ` Anshuman Khandual
@ 2014-04-02  7:02   ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel
  Cc: avagin, oleg, roland, mikey, benh, Anshuman Khandual

This patch adds following new set of ptrace request macros for miscellaneous
registers expanding the existing ptrace ABI on PowerPC.

	/* Miscellaneous registers */
	PTRACE_GETMSCREGS
	PTRACE_SETMSCREGS

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/ptrace.h | 10 ++++
 arch/powerpc/kernel/ptrace.c           | 91 +++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h
index 1a12c36..bce1055 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -241,6 +241,16 @@ struct pt_regs {
 #define PTRACE_GETTM_CVMXREGS	0x76
 #define PTRACE_SETTM_CVMXREGS	0x77
 
+/* Miscellaneous registers */
+#define PTRACE_GETMSCREGS      0x78
+#define PTRACE_SETMSCREGS      0x79
+
+/*
+ * XXX: A note to application developers. The existing data layout
+ * of the above four ptrace requests can change when new registers
+ * are available for each category in forthcoming processors.
+ */
+
 #ifndef __ASSEMBLY__
 
 struct ppc_debug_info {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 9fbcb6a..2893958 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1054,6 +1054,76 @@ static int tm_cvmx_set(struct task_struct *target, const struct user_regset *reg
 #endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
+ * Miscellaneous Registers
+ *
+ * struct {
+ * 	unsigned long dscr;
+ *	unsigned long ppr;
+ * 	unsigned long tar;
+ * };
+ */
+static int misc_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* DSCR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, dscr) + sizeof(unsigned long) +
+		     		sizeof(unsigned long) != offsetof(struct thread_struct, ppr));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.ppr, sizeof(unsigned long),
+					  2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, ppr) + sizeof(unsigned long)
+		     			!= offsetof(struct thread_struct, tar));
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.tar, 2 * sizeof(unsigned long),
+					  3 * sizeof(unsigned long));
+	return ret;
+}
+
+static int misc_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	/* DSCR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, dscr) + sizeof(unsigned long) +
+		     	sizeof(unsigned long) != offsetof(struct thread_struct, ppr));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr, sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, ppr) + sizeof(unsigned long)
+						!= offsetof(struct thread_struct, tar));
+
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar, 2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
  * These are our native regset flavors.
  */
 enum powerpc_regset {
@@ -1072,8 +1142,9 @@ enum powerpc_regset {
 	REGSET_TM_SPR,		/* TM specific SPR */
 	REGSET_TM_CGPR,		/* TM checkpointed GPR */
 	REGSET_TM_CFPR,		/* TM checkpointed FPR */
-	REGSET_TM_CVMX		/* TM checkpointed VMX */
+	REGSET_TM_CVMX,		/* TM checkpointed VMX */
 #endif
+	REGSET_MISC		/* Miscellaneous */
 };
 
 static const struct user_regset native_regsets[] = {
@@ -1130,6 +1201,11 @@ static const struct user_regset native_regsets[] = {
 		.get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = 3,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = misc_get, .set = misc_set
+	},
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -1320,6 +1396,11 @@ static const struct user_regset compat_regsets[] = {
 		.get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = 3,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = misc_get, .set = misc_set
+	},
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
@@ -2269,6 +2350,14 @@ long arch_ptrace(struct task_struct *child, long request,
 		return copy_regset_from_user(child, &user_ppc_native_view,
 					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+	case PTRACE_GETMSCREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					REGSET_MISC, 0, 3 * sizeof(u64),
+					datavp);
+	case PTRACE_SETMSCREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					REGSET_MISC, 0, 3 * sizeof(u64),
+					datavp);
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
-- 
1.7.11.7


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/3] powerpc, ptrace: Add new ptrace request macro for miscellaneous registers
@ 2014-04-02  7:02   ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  7:02 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, avagin, oleg, roland, Anshuman Khandual

This patch adds following new set of ptrace request macros for miscellaneous
registers expanding the existing ptrace ABI on PowerPC.

	/* Miscellaneous registers */
	PTRACE_GETMSCREGS
	PTRACE_SETMSCREGS

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/ptrace.h | 10 ++++
 arch/powerpc/kernel/ptrace.c           | 91 +++++++++++++++++++++++++++++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h
index 1a12c36..bce1055 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -241,6 +241,16 @@ struct pt_regs {
 #define PTRACE_GETTM_CVMXREGS	0x76
 #define PTRACE_SETTM_CVMXREGS	0x77
 
+/* Miscellaneous registers */
+#define PTRACE_GETMSCREGS      0x78
+#define PTRACE_SETMSCREGS      0x79
+
+/*
+ * XXX: A note to application developers. The existing data layout
+ * of the above four ptrace requests can change when new registers
+ * are available for each category in forthcoming processors.
+ */
+
 #ifndef __ASSEMBLY__
 
 struct ppc_debug_info {
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 9fbcb6a..2893958 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1054,6 +1054,76 @@ static int tm_cvmx_set(struct task_struct *target, const struct user_regset *reg
 #endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
+ * Miscellaneous Registers
+ *
+ * struct {
+ * 	unsigned long dscr;
+ *	unsigned long ppr;
+ * 	unsigned long tar;
+ * };
+ */
+static int misc_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* DSCR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, dscr) + sizeof(unsigned long) +
+		     		sizeof(unsigned long) != offsetof(struct thread_struct, ppr));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.ppr, sizeof(unsigned long),
+					  2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, ppr) + sizeof(unsigned long)
+		     			!= offsetof(struct thread_struct, tar));
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  &target->thread.tar, 2 * sizeof(unsigned long),
+					  3 * sizeof(unsigned long));
+	return ret;
+}
+
+static int misc_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	/* DSCR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, dscr) + sizeof(unsigned long) +
+		     	sizeof(unsigned long) != offsetof(struct thread_struct, ppr));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr, sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+
+	BUILD_BUG_ON(offsetof(struct thread_struct, ppr) + sizeof(unsigned long)
+						!= offsetof(struct thread_struct, tar));
+
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar, 2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
  * These are our native regset flavors.
  */
 enum powerpc_regset {
@@ -1072,8 +1142,9 @@ enum powerpc_regset {
 	REGSET_TM_SPR,		/* TM specific SPR */
 	REGSET_TM_CGPR,		/* TM checkpointed GPR */
 	REGSET_TM_CFPR,		/* TM checkpointed FPR */
-	REGSET_TM_CVMX		/* TM checkpointed VMX */
+	REGSET_TM_CVMX,		/* TM checkpointed VMX */
 #endif
+	REGSET_MISC		/* Miscellaneous */
 };
 
 static const struct user_regset native_regsets[] = {
@@ -1130,6 +1201,11 @@ static const struct user_regset native_regsets[] = {
 		.get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = 3,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = misc_get, .set = misc_set
+	},
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -1320,6 +1396,11 @@ static const struct user_regset compat_regsets[] = {
 		.get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = 3,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = misc_get, .set = misc_set
+	},
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
@@ -2269,6 +2350,14 @@ long arch_ptrace(struct task_struct *child, long request,
 		return copy_regset_from_user(child, &user_ppc_native_view,
 					   REGSET_TM_CVMX, 0, (33 * sizeof(vector128) + sizeof(u32)), datavp);
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+	case PTRACE_GETMSCREGS:
+		return copy_regset_to_user(child, &user_ppc_native_view,
+					REGSET_MISC, 0, 3 * sizeof(u64),
+					datavp);
+	case PTRACE_SETMSCREGS:
+		return copy_regset_from_user(child, &user_ppc_native_view,
+					REGSET_MISC, 0, 3 * sizeof(u64),
+					datavp);
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-02  7:02 ` Anshuman Khandual
@ 2014-04-02  9:32   ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  9:32 UTC (permalink / raw)
  To: Anshuman Khandual
  Cc: linuxppc-dev, linux-kernel, avagin, oleg, roland, mikey, benh

On 04/02/2014 12:32 PM, Anshuman Khandual wrote:
> 	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

There is a problem in here which I forgot to mention. The running DSCR value
comes from thread->dscr component of the target process. While we are inside the
transaction (which is the case here as we are stuck at "b ." instruction and
have not reached TEND) thread->dscr should have the running value of the DSCR
register at that point of time. Here we expect the DSCR value to be 5 instead
of 0 as shown in the output above. During the tests when I moved the "b ." after
TEND, the thread->dscr gets the value of 5 while all check pointed reg values are
thrown away. I believe there is some problem in the way thread->dscr context
is saved away inside the TM section. Will look into this problem further and
keep informed.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-02  9:32   ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-02  9:32 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: mikey, avagin, oleg, linux-kernel, linuxppc-dev, roland

On 04/02/2014 12:32 PM, Anshuman Khandual wrote:
> 	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

There is a problem in here which I forgot to mention. The running DSCR value
comes from thread->dscr component of the target process. While we are inside the
transaction (which is the case here as we are stuck at "b ." instruction and
have not reached TEND) thread->dscr should have the running value of the DSCR
register at that point of time. Here we expect the DSCR value to be 5 instead
of 0 as shown in the output above. During the tests when I moved the "b ." after
TEND, the thread->dscr gets the value of 5 while all check pointed reg values are
thrown away. I believe there is some problem in the way thread->dscr context
is saved away inside the TM section. Will look into this problem further and
keep informed.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
  2014-04-02  7:02   ` Anshuman Khandual
@ 2014-04-25 23:42     ` Pedro Alves
  -1 siblings, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-04-25 23:42 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: linuxppc-dev, linux-kernel, avagin, oleg, mikey, benh

On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
> This patch adds following new sets of ptrace request macros for transactional
> memory expanding the existing ptrace ABI on PowerPC.
> 
> 	/* TM special purpose registers */
> 	PTRACE_GETTM_SPRREGS
> 	PTRACE_SETTM_SPRREGS
> 
> 	/* TM checkpointed GPR registers */
> 	PTRACE_GETTM_CGPRREGS
> 	PTRACE_SETTM_CGPRREGS
> 
> 	/* TM checkpointed FPR registers */
> 	PTRACE_GETTM_CFPRREGS
> 	PTRACE_SETTM_CFPRREGS
> 
> 	/* TM checkpointed VMX registers */
> 	PTRACE_GETTM_CVMXREGS
> 	PTRACE_SETTM_CVMXREGS

Urgh, we're _still_ adding specialized register specific calls?
Why aren't these exported as new register sets, accessible through
PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
Modern Way to do things.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
@ 2014-04-25 23:42     ` Pedro Alves
  0 siblings, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-04-25 23:42 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: mikey, avagin, oleg, linux-kernel, linuxppc-dev

On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
> This patch adds following new sets of ptrace request macros for transactional
> memory expanding the existing ptrace ABI on PowerPC.
> 
> 	/* TM special purpose registers */
> 	PTRACE_GETTM_SPRREGS
> 	PTRACE_SETTM_SPRREGS
> 
> 	/* TM checkpointed GPR registers */
> 	PTRACE_GETTM_CGPRREGS
> 	PTRACE_SETTM_CGPRREGS
> 
> 	/* TM checkpointed FPR registers */
> 	PTRACE_GETTM_CFPRREGS
> 	PTRACE_SETTM_CFPRREGS
> 
> 	/* TM checkpointed VMX registers */
> 	PTRACE_GETTM_CVMXREGS
> 	PTRACE_SETTM_CVMXREGS

Urgh, we're _still_ adding specialized register specific calls?
Why aren't these exported as new register sets, accessible through
PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
Modern Way to do things.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
  2014-04-25 23:42     ` Pedro Alves
@ 2014-04-28 10:30       ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-28 10:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: linuxppc-dev, linux-kernel, avagin, oleg, mikey, benh

On 04/26/2014 05:12 AM, Pedro Alves wrote:
> On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
>> This patch adds following new sets of ptrace request macros for transactional
>> memory expanding the existing ptrace ABI on PowerPC.
>>
>> 	/* TM special purpose registers */
>> 	PTRACE_GETTM_SPRREGS
>> 	PTRACE_SETTM_SPRREGS
>>
>> 	/* TM checkpointed GPR registers */
>> 	PTRACE_GETTM_CGPRREGS
>> 	PTRACE_SETTM_CGPRREGS
>>
>> 	/* TM checkpointed FPR registers */
>> 	PTRACE_GETTM_CFPRREGS
>> 	PTRACE_SETTM_CFPRREGS
>>
>> 	/* TM checkpointed VMX registers */
>> 	PTRACE_GETTM_CVMXREGS
>> 	PTRACE_SETTM_CVMXREGS
> 
> Urgh, we're _still_ adding specialized register specific calls?
> Why aren't these exported as new register sets, accessible through
> PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
> Modern Way to do things.

All these new register sets can be accessed through PTRACE_GETREGSET
/SETREGSET requests with the new NT_PPC_* core note types added in the
previous patch. PowerPC already has some register specific ptrace
requests, so thought of adding some new requests for transactional
memory purpose. But yes these are redundant and can be dropped.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
@ 2014-04-28 10:30       ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-28 10:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: mikey, avagin, oleg, linux-kernel, linuxppc-dev

On 04/26/2014 05:12 AM, Pedro Alves wrote:
> On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
>> This patch adds following new sets of ptrace request macros for transactional
>> memory expanding the existing ptrace ABI on PowerPC.
>>
>> 	/* TM special purpose registers */
>> 	PTRACE_GETTM_SPRREGS
>> 	PTRACE_SETTM_SPRREGS
>>
>> 	/* TM checkpointed GPR registers */
>> 	PTRACE_GETTM_CGPRREGS
>> 	PTRACE_SETTM_CGPRREGS
>>
>> 	/* TM checkpointed FPR registers */
>> 	PTRACE_GETTM_CFPRREGS
>> 	PTRACE_SETTM_CFPRREGS
>>
>> 	/* TM checkpointed VMX registers */
>> 	PTRACE_GETTM_CVMXREGS
>> 	PTRACE_SETTM_CVMXREGS
> 
> Urgh, we're _still_ adding specialized register specific calls?
> Why aren't these exported as new register sets, accessible through
> PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
> Modern Way to do things.

All these new register sets can be accessed through PTRACE_GETREGSET
/SETREGSET requests with the new NT_PPC_* core note types added in the
previous patch. PowerPC already has some register specific ptrace
requests, so thought of adding some new requests for transactional
memory purpose. But yes these are redundant and can be dropped.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-02  9:32   ` Anshuman Khandual
@ 2014-04-29  7:00     ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29  7:00 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: mikey, avagin, oleg, linux-kernel, linuxppc-dev, roland

On 04/02/2014 03:02 PM, Anshuman Khandual wrote:
> On 04/02/2014 12:32 PM, Anshuman Khandual wrote:
>> 	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
> 
> There is a problem in here which I forgot to mention. The running DSCR value
> comes from thread->dscr component of the target process. While we are inside the
> transaction (which is the case here as we are stuck at "b ." instruction and
> have not reached TEND) thread->dscr should have the running value of the DSCR
> register at that point of time. Here we expect the DSCR value to be 5 instead
> of 0 as shown in the output above. During the tests when I moved the "b ." after
> TEND, the thread->dscr gets the value of 5 while all check pointed reg values are
> thrown away. I believe there is some problem in the way thread->dscr context
> is saved away inside the TM section. Will look into this problem further and
> keep informed.

Reason behind this inconsistent DSCR register value is because of the following commit
where the kernel reverts the DSCR register into a default value to avoid running with
the user set value for a long time, thus preventing any potential performance degradation.
Same reason applies to the PPR register as well. So its not a problem but an expected
behaviour.

commit e9bdc3d6143d1c4b8d8ce5231fc958268331f983
Author: Michael Neuling <mikey@neuling.org>
Date:   Thu Sep 26 13:29:09 2013 +1000

    powerpc/tm: Switch out userspace PPR and DSCR sooner

    When we do a treclaim or trecheckpoint we end up running with userspace
    PPR and DSCR values.  Currently we don't do anything special to avoid
    running with user values which could cause a severe performance
    degradation.

    This patch moves the PPR and DSCR save and restore around treclaim and
    trecheckpoint so that we run with user values for a much shorter period.
    More care is taken with the PPR as it's impact is greater than the DSCR.

    This is similar to user exceptions, where we run HTM_MEDIUM early to
    ensure that we don't run with a userspace PPR values in the kernel.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-29  7:00     ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29  7:00 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: mikey, avagin, linux-kernel, oleg, linuxppc-dev, roland

On 04/02/2014 03:02 PM, Anshuman Khandual wrote:
> On 04/02/2014 12:32 PM, Anshuman Khandual wrote:
>> 	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
> 
> There is a problem in here which I forgot to mention. The running DSCR value
> comes from thread->dscr component of the target process. While we are inside the
> transaction (which is the case here as we are stuck at "b ." instruction and
> have not reached TEND) thread->dscr should have the running value of the DSCR
> register at that point of time. Here we expect the DSCR value to be 5 instead
> of 0 as shown in the output above. During the tests when I moved the "b ." after
> TEND, the thread->dscr gets the value of 5 while all check pointed reg values are
> thrown away. I believe there is some problem in the way thread->dscr context
> is saved away inside the TM section. Will look into this problem further and
> keep informed.

Reason behind this inconsistent DSCR register value is because of the following commit
where the kernel reverts the DSCR register into a default value to avoid running with
the user set value for a long time, thus preventing any potential performance degradation.
Same reason applies to the PPR register as well. So its not a problem but an expected
behaviour.

commit e9bdc3d6143d1c4b8d8ce5231fc958268331f983
Author: Michael Neuling <mikey@neuling.org>
Date:   Thu Sep 26 13:29:09 2013 +1000

    powerpc/tm: Switch out userspace PPR and DSCR sooner

    When we do a treclaim or trecheckpoint we end up running with userspace
    PPR and DSCR values.  Currently we don't do anything special to avoid
    running with user values which could cause a severe performance
    degradation.

    This patch moves the PPR and DSCR save and restore around treclaim and
    trecheckpoint so that we run with user values for a much shorter period.
    More care is taken with the PPR as it's impact is greater than the DSCR.

    This is similar to user exceptions, where we run HTM_MEDIUM early to
    ensure that we don't run with a userspace PPR values in the kernel.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-29  7:00     ` Anshuman Khandual
  (?)
@ 2014-04-29  7:06     ` Michael Neuling
  2014-04-29  7:59         ` Anshuman Khandual
  -1 siblings, 1 reply; 28+ messages in thread
From: Michael Neuling @ 2014-04-29  7:06 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

[-- Attachment #1: Type: text/plain, Size: 3581 bytes --]

How is it causing the problem?

Mikey

On 29 Apr 2014 17:02, "Anshuman Khandual" <khandual@linux.vnet.ibm.com>
wrote:
>
> On 04/02/2014 03:02 PM, Anshuman Khandual wrote:
> > On 04/02/2014 12:32 PM, Anshuman Khandual wrote:
> >>      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
> >
> > There is a problem in here which I forgot to mention. The running DSCR
value
> > comes from thread->dscr component of the target process. While we are
inside the
> > transaction (which is the case here as we are stuck at "b ."
instruction and
> > have not reached TEND) thread->dscr should have the running value of
the DSCR
> > register at that point of time. Here we expect the DSCR value to be 5
instead
> > of 0 as shown in the output above. During the tests when I moved the "b
." after
> > TEND, the thread->dscr gets the value of 5 while all check pointed reg
values are
> > thrown away. I believe there is some problem in the way thread->dscr
context
> > is saved away inside the TM section. Will look into this problem
further and
> > keep informed.
>
> Reason behind this inconsistent DSCR register value is because of the
following commit
> where the kernel reverts the DSCR register into a default value to avoid
running with
> the user set value for a long time, thus preventing any potential
performance degradation.
> Same reason applies to the PPR register as well. So its not a problem but
an expected
> behaviour.
>
> commit e9bdc3d6143d1c4b8d8ce5231fc958268331f983
> Author: Michael Neuling <mikey@neuling.org>
> Date:   Thu Sep 26 13:29:09 2013 +1000
>
>     powerpc/tm: Switch out userspace PPR and DSCR sooner
>
>     When we do a treclaim or trecheckpoint we end up running with
userspace
>     PPR and DSCR values.  Currently we don't do anything special to avoid
>     running with user values which could cause a severe performance
>     degradation.
>
>     This patch moves the PPR and DSCR save and restore around treclaim and
>     trecheckpoint so that we run with user values for a much shorter
period.
>     More care is taken with the PPR as it's impact is greater than the
DSCR.
>
>     This is similar to user exceptions, where we run HTM_MEDIUM early to
>     ensure that we don't run with a userspace PPR values in the kernel.
>

[-- Attachment #2: Type: text/html, Size: 4832 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-29  7:06     ` Michael Neuling
@ 2014-04-29  7:59         ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29  7:59 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Linux PPC dev, avagin, roland, oleg, linux-kernel

On 04/29/2014 12:36 PM, Michael Neuling wrote:
> How is it causing the problem?

As mentioned before, what I thought to be a problem is
something expected behaviour. So it's not a problem any
more. DSCR value inside the transaction will fall back
to default as kernel wont let user specified value to
remain applied for a long time.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-29  7:59         ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29  7:59 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

On 04/29/2014 12:36 PM, Michael Neuling wrote:
> How is it causing the problem?

As mentioned before, what I thought to be a problem is
something expected behaviour. So it's not a problem any
more. DSCR value inside the transaction will fall back
to default as kernel wont let user specified value to
remain applied for a long time.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-29  7:59         ` Anshuman Khandual
  (?)
@ 2014-04-29  8:22         ` Michael Neuling
  2014-04-29 12:22             ` Anshuman Khandual
  -1 siblings, 1 reply; 28+ messages in thread
From: Michael Neuling @ 2014-04-29  8:22 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

[-- Attachment #1: Type: text/plain, Size: 882 bytes --]

That's not what that patch does. It shouldn't make any user visible changes
to DSCR or PPR.

Over syscall PPR and DSCR may change. Depending on your test case, that may
be your problem.

Mikey
On 29 Apr 2014 18:02, "Anshuman Khandual" <khandual@linux.vnet.ibm.com>
wrote:

> On 04/29/2014 12:36 PM, Michael Neuling wrote:
> > How is it causing the problem?
>
> As mentioned before, what I thought to be a problem is
> something expected behaviour. So it's not a problem any
> more. DSCR value inside the transaction will fall back
> to default as kernel wont let user specified value to
> remain applied for a long time.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
>

[-- Attachment #2: Type: text/html, Size: 1418 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-29  8:22         ` Michael Neuling
@ 2014-04-29 12:22             ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29 12:22 UTC (permalink / raw)
  To: Michael Neuling; +Cc: avagin, roland, oleg, Linux PPC dev, linux-kernel

On 04/29/2014 01:52 PM, Michael Neuling wrote:
> That's not what that patch does. It shouldn't make any user visible changes
> to DSCR or PPR.

It may not when it runs uninterrupted but after the tracee process has stopped,
thread.dscr reflects the default DSCR value as mentioned before. This can be
proved by changing the "dscr_default" value in arch/powerpc/sysfs.c file.

> 
> Over syscall PPR and DSCR may change. Depending on your test case, that may
> be your problem.

I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
tm_recheckpoint path might be crossed which is causing this dscr_default value
to go into thread_struct.


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-29 12:22             ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-29 12:22 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

On 04/29/2014 01:52 PM, Michael Neuling wrote:
> That's not what that patch does. It shouldn't make any user visible changes
> to DSCR or PPR.

It may not when it runs uninterrupted but after the tracee process has stopped,
thread.dscr reflects the default DSCR value as mentioned before. This can be
proved by changing the "dscr_default" value in arch/powerpc/sysfs.c file.

> 
> Over syscall PPR and DSCR may change. Depending on your test case, that may
> be your problem.

I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
tm_recheckpoint path might be crossed which is causing this dscr_default value
to go into thread_struct.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-29 12:22             ` Anshuman Khandual
@ 2014-04-30  0:29               ` Michael Neuling
  -1 siblings, 0 replies; 28+ messages in thread
From: Michael Neuling @ 2014-04-30  0:29 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: avagin, roland, oleg, Linux PPC dev, linux-kernel

Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:

> On 04/29/2014 01:52 PM, Michael Neuling wrote:
> > That's not what that patch does. It shouldn't make any user visible changes
> > to DSCR or PPR.
> 
> It may not when it runs uninterrupted but after the tracee process has
> stopped, thread.dscr reflects the default DSCR value as mentioned
> before. This can be proved by changing the "dscr_default" value in
> arch/powerpc/sysfs.c file.

The intention with DSCR is that if the user changes the DSCR, the kernel
should always save/restore it.  If you are seeing something else, then
that is a bug.  Anton has a test case for this here:

  http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c

If that is failing, then there is a bug that we need to fix.

The PPR is the same, except that the kernel can change it over a
syscall.

> > Over syscall PPR and DSCR may change.

Sorry, this should be only PPR.  DSCR shouldn't change over a syscall,
at least that's the intention.

> > Depending on your test case, that may
> > be your problem.
> 
> I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
> tm_recheckpoint path might be crossed which is causing this dscr_default value
> to go into thread_struct.

That shouldn't happen.  If that's happening, it's a bug.

Mikey

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-30  0:29               ` Michael Neuling
  0 siblings, 0 replies; 28+ messages in thread
From: Michael Neuling @ 2014-04-30  0:29 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:

> On 04/29/2014 01:52 PM, Michael Neuling wrote:
> > That's not what that patch does. It shouldn't make any user visible changes
> > to DSCR or PPR.
> 
> It may not when it runs uninterrupted but after the tracee process has
> stopped, thread.dscr reflects the default DSCR value as mentioned
> before. This can be proved by changing the "dscr_default" value in
> arch/powerpc/sysfs.c file.

The intention with DSCR is that if the user changes the DSCR, the kernel
should always save/restore it.  If you are seeing something else, then
that is a bug.  Anton has a test case for this here:

  http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c

If that is failing, then there is a bug that we need to fix.

The PPR is the same, except that the kernel can change it over a
syscall.

> > Over syscall PPR and DSCR may change.

Sorry, this should be only PPR.  DSCR shouldn't change over a syscall,
at least that's the intention.

> > Depending on your test case, that may
> > be your problem.
> 
> I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
> tm_recheckpoint path might be crossed which is causing this dscr_default value
> to go into thread_struct.

That shouldn't happen.  If that's happening, it's a bug.

Mikey

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
  2014-04-30  0:29               ` Michael Neuling
@ 2014-04-30  8:16                 ` Anshuman Khandual
  -1 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-30  8:16 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Linux PPC dev, linux-kernel, avagin, roland, oleg

On 04/30/2014 05:59 AM, Michael Neuling wrote:
> Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:
> 
>> On 04/29/2014 01:52 PM, Michael Neuling wrote:
>>> That's not what that patch does. It shouldn't make any user visible changes
>>> to DSCR or PPR.
>>
>> It may not when it runs uninterrupted but after the tracee process has
>> stopped, thread.dscr reflects the default DSCR value as mentioned
>> before. This can be proved by changing the "dscr_default" value in
>> arch/powerpc/sysfs.c file.
> 
> The intention with DSCR is that if the user changes the DSCR, the kernel
> should always save/restore it.  If you are seeing something else, then
> that is a bug.  Anton has a test case for this here:
> 
>   http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c
> 
> If that is failing, then there is a bug that we need to fix.
> 

Anton's above DSCR test passed.

> The PPR is the same, except that the kernel can change it over a
> syscall.
> 
>>> Over syscall PPR and DSCR may change.
> 
> Sorry, this should be only PPR.  DSCR shouldn't change over a syscall,
> at least that's the intention.
> 
>>> Depending on your test case, that may
>>> be your problem.
>>
>> I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
>> tm_recheckpoint path might be crossed which is causing this dscr_default value
>> to go into thread_struct.
> 
> That shouldn't happen.  If that's happening, it's a bug.

I would believe this is happening. Also after reverting the commit
e9bdc3d6143d1c4b8d8ce5231, thread.dscr reflects the same value as that
of thread.tm_dscr which is the check pointed DSCR register value just
before the transaction started. So even the NIP has moved passed the point
where the user changes DSCR inside the transaction, thread.dscr is unable
to capture that latest value. But thread.dscr must contain the latest user
changed value of DSCR which is definitely not happening here. So there is
a problem we need to fix. 



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 0/3] Add new ptrace request macros on PowerPC
@ 2014-04-30  8:16                 ` Anshuman Khandual
  0 siblings, 0 replies; 28+ messages in thread
From: Anshuman Khandual @ 2014-04-30  8:16 UTC (permalink / raw)
  To: Michael Neuling; +Cc: Linux PPC dev, oleg, linux-kernel, roland, avagin

On 04/30/2014 05:59 AM, Michael Neuling wrote:
> Anshuman Khandual <khandual@linux.vnet.ibm.com> wrote:
> 
>> On 04/29/2014 01:52 PM, Michael Neuling wrote:
>>> That's not what that patch does. It shouldn't make any user visible changes
>>> to DSCR or PPR.
>>
>> It may not when it runs uninterrupted but after the tracee process has
>> stopped, thread.dscr reflects the default DSCR value as mentioned
>> before. This can be proved by changing the "dscr_default" value in
>> arch/powerpc/sysfs.c file.
> 
> The intention with DSCR is that if the user changes the DSCR, the kernel
> should always save/restore it.  If you are seeing something else, then
> that is a bug.  Anton has a test case for this here:
> 
>   http://ozlabs.org/~anton/junkcode/dscr_explicit_test.c
> 
> If that is failing, then there is a bug that we need to fix.
> 

Anton's above DSCR test passed.

> The PPR is the same, except that the kernel can change it over a
> syscall.
> 
>>> Over syscall PPR and DSCR may change.
> 
> Sorry, this should be only PPR.  DSCR shouldn't change over a syscall,
> at least that's the intention.
> 
>>> Depending on your test case, that may
>>> be your problem.
>>
>> I would guess when the tracee process stops for ptrace analysis, tm_reclaim or
>> tm_recheckpoint path might be crossed which is causing this dscr_default value
>> to go into thread_struct.
> 
> That shouldn't happen.  If that's happening, it's a bug.

I would believe this is happening. Also after reverting the commit
e9bdc3d6143d1c4b8d8ce5231, thread.dscr reflects the same value as that
of thread.tm_dscr which is the check pointed DSCR register value just
before the transaction started. So even the NIP has moved passed the point
where the user changes DSCR inside the transaction, thread.dscr is unable
to capture that latest value. But thread.dscr must contain the latest user
changed value of DSCR which is definitely not happening here. So there is
a problem we need to fix. 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
  2014-04-28 10:30       ` Anshuman Khandual
@ 2014-05-01 13:41         ` Pedro Alves
  -1 siblings, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-05-01 13:41 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: linuxppc-dev, linux-kernel, avagin, oleg, mikey, benh

On 04/28/2014 11:30 AM, Anshuman Khandual wrote:
> On 04/26/2014 05:12 AM, Pedro Alves wrote:
>> On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
>>> This patch adds following new sets of ptrace request macros for transactional
>>> memory expanding the existing ptrace ABI on PowerPC.
>>>
>>> 	/* TM special purpose registers */
>>> 	PTRACE_GETTM_SPRREGS
>>> 	PTRACE_SETTM_SPRREGS
>>>
>>> 	/* TM checkpointed GPR registers */
>>> 	PTRACE_GETTM_CGPRREGS
>>> 	PTRACE_SETTM_CGPRREGS
>>>
>>> 	/* TM checkpointed FPR registers */
>>> 	PTRACE_GETTM_CFPRREGS
>>> 	PTRACE_SETTM_CFPRREGS
>>>
>>> 	/* TM checkpointed VMX registers */
>>> 	PTRACE_GETTM_CVMXREGS
>>> 	PTRACE_SETTM_CVMXREGS
>>
>> Urgh, we're _still_ adding specialized register specific calls?
>> Why aren't these exported as new register sets, accessible through
>> PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
>> Modern Way to do things.
> 
> All these new register sets can be accessed through PTRACE_GETREGSET
> /SETREGSET requests with the new NT_PPC_* core note types added in the
> previous patch. PowerPC already has some register specific ptrace
> requests, so thought of adding some new requests for transactional
> memory purpose. But yes these are redundant and can be dropped.

Thank you.  I assume you guys will be working on gdb support for this,
and I'm really hoping that transaction support in the kernel is being
made uniform across archs.  E.g., on s390, PTRACE_GETREGSET returns
ENODATA if the ptracee was interrupted outside transactions.

  https://sourceware.org/ml/gdb-patches/2013-06/msg00273.html

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory
@ 2014-05-01 13:41         ` Pedro Alves
  0 siblings, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-05-01 13:41 UTC (permalink / raw)
  To: Anshuman Khandual; +Cc: mikey, avagin, oleg, linux-kernel, linuxppc-dev

On 04/28/2014 11:30 AM, Anshuman Khandual wrote:
> On 04/26/2014 05:12 AM, Pedro Alves wrote:
>> On 04/02/2014 08:02 AM, Anshuman Khandual wrote:
>>> This patch adds following new sets of ptrace request macros for transactional
>>> memory expanding the existing ptrace ABI on PowerPC.
>>>
>>> 	/* TM special purpose registers */
>>> 	PTRACE_GETTM_SPRREGS
>>> 	PTRACE_SETTM_SPRREGS
>>>
>>> 	/* TM checkpointed GPR registers */
>>> 	PTRACE_GETTM_CGPRREGS
>>> 	PTRACE_SETTM_CGPRREGS
>>>
>>> 	/* TM checkpointed FPR registers */
>>> 	PTRACE_GETTM_CFPRREGS
>>> 	PTRACE_SETTM_CFPRREGS
>>>
>>> 	/* TM checkpointed VMX registers */
>>> 	PTRACE_GETTM_CVMXREGS
>>> 	PTRACE_SETTM_CVMXREGS
>>
>> Urgh, we're _still_ adding specialized register specific calls?
>> Why aren't these exported as new register sets, accessible through
>> PTRACE_GETREGSET /  PTRACE_SETREGSET?  That's supposed to be the
>> Modern Way to do things.
> 
> All these new register sets can be accessed through PTRACE_GETREGSET
> /SETREGSET requests with the new NT_PPC_* core note types added in the
> previous patch. PowerPC already has some register specific ptrace
> requests, so thought of adding some new requests for transactional
> memory purpose. But yes these are redundant and can be dropped.

Thank you.  I assume you guys will be working on gdb support for this,
and I'm really hoping that transaction support in the kernel is being
made uniform across archs.  E.g., on s390, PTRACE_GETREGSET returns
ENODATA if the ptracee was interrupted outside transactions.

  https://sourceware.org/ml/gdb-patches/2013-06/msg00273.html

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2014-05-01 13:41 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-02  7:02 [PATCH 0/3] Add new ptrace request macros on PowerPC Anshuman Khandual
2014-04-02  7:02 ` Anshuman Khandual
2014-04-02  7:02 ` [PATCH 1/3] elf: Add some new PowerPC specifc note sections Anshuman Khandual
2014-04-02  7:02   ` Anshuman Khandual
2014-04-02  7:02 ` [PATCH 2/3] powerpc, ptrace: Add new ptrace request macros for transactional memory Anshuman Khandual
2014-04-02  7:02   ` Anshuman Khandual
2014-04-25 23:42   ` Pedro Alves
2014-04-25 23:42     ` Pedro Alves
2014-04-28 10:30     ` Anshuman Khandual
2014-04-28 10:30       ` Anshuman Khandual
2014-05-01 13:41       ` Pedro Alves
2014-05-01 13:41         ` Pedro Alves
2014-04-02  7:02 ` [PATCH 3/3] powerpc, ptrace: Add new ptrace request macro for miscellaneous registers Anshuman Khandual
2014-04-02  7:02   ` Anshuman Khandual
2014-04-02  9:32 ` [PATCH 0/3] Add new ptrace request macros on PowerPC Anshuman Khandual
2014-04-02  9:32   ` Anshuman Khandual
2014-04-29  7:00   ` Anshuman Khandual
2014-04-29  7:00     ` Anshuman Khandual
2014-04-29  7:06     ` Michael Neuling
2014-04-29  7:59       ` Anshuman Khandual
2014-04-29  7:59         ` Anshuman Khandual
2014-04-29  8:22         ` Michael Neuling
2014-04-29 12:22           ` Anshuman Khandual
2014-04-29 12:22             ` Anshuman Khandual
2014-04-30  0:29             ` Michael Neuling
2014-04-30  0:29               ` Michael Neuling
2014-04-30  8:16               ` Anshuman Khandual
2014-04-30  8:16                 ` Anshuman Khandual

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.