aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnshuman Khandual <khandual@linux.vnet.ibm.com>2016-07-27 22:57:40 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-07-31 21:15:21 -0400
commit08e1c01d6aedf00af04d9571a0a5d5867298b719 (patch)
treeb04d0692fc5d812b1ebafad9c832df42a3731e3b
parent9d3918f7c0e516bb8782915cdb2f8cbdbf6c4f9b (diff)
powerpc/ptrace: Enable support for TM SPR state
This patch enables support for TM SPR state related ELF core note NT_PPC_TM_SPR based ptrace requests through PTRACE_GETREGSET, PTRACE_SETREGSET calls. This is achieved through adding a register set REGSET_TM_SPR in powerpc corresponding to the ELF core note section added. It implements the get, set and active functions for this new register set added. Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com> Signed-off-by: Simon Guo <wei.guo.simon@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/uapi/asm/elf.h1
-rw-r--r--arch/powerpc/kernel/ptrace.c143
2 files changed, 143 insertions, 1 deletions
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index 1549172aa258..e703c646163b 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -93,6 +93,7 @@
93#define ELF_NFPREG 33 /* includes fpscr */ 93#define ELF_NFPREG 33 /* includes fpscr */
94#define ELF_NVMX 34 /* includes all vector registers */ 94#define ELF_NVMX 34 /* includes all vector registers */
95#define ELF_NVSX 32 /* includes all VSX registers */ 95#define ELF_NVSX 32 /* includes all VSX registers */
96#define ELF_NTMSPRREG 3 /* include tfhar, tfiar, texasr */
96 97
97typedef unsigned long elf_greg_t64; 98typedef unsigned long elf_greg_t64;
98typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; 99typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index df6afe7da4da..f654224d2653 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -66,6 +66,7 @@ struct pt_regs_offset {
66 66
67#define TVSO(f) (offsetof(struct thread_vr_state, f)) 67#define TVSO(f) (offsetof(struct thread_vr_state, f))
68#define TFSO(f) (offsetof(struct thread_fp_state, f)) 68#define TFSO(f) (offsetof(struct thread_fp_state, f))
69#define TSO(f) (offsetof(struct thread_struct, f))
69 70
70static const struct pt_regs_offset regoffset_table[] = { 71static const struct pt_regs_offset regoffset_table[] = {
71 GPR_OFFSET_NAME(0), 72 GPR_OFFSET_NAME(0),
@@ -1412,7 +1413,136 @@ static int tm_cvsx_set(struct task_struct *target,
1412 1413
1413 return ret; 1414 return ret;
1414} 1415}
1415#endif 1416
1417/**
1418 * tm_spr_active - get active number of registers in TM SPR
1419 * @target: The target task.
1420 * @regset: The user regset structure.
1421 *
1422 * This function checks the active number of available
1423 * regisers in the transactional memory SPR category.
1424 */
1425static int tm_spr_active(struct task_struct *target,
1426 const struct user_regset *regset)
1427{
1428 if (!cpu_has_feature(CPU_FTR_TM))
1429 return -ENODEV;
1430
1431 return regset->n;
1432}
1433
1434/**
1435 * tm_spr_get - get the TM related SPR registers
1436 * @target: The target task.
1437 * @regset: The user regset structure.
1438 * @pos: The buffer position.
1439 * @count: Number of bytes to copy.
1440 * @kbuf: Kernel buffer to copy from.
1441 * @ubuf: User buffer to copy into.
1442 *
1443 * This function gets transactional memory related SPR registers.
1444 * The userspace interface buffer layout is as follows.
1445 *
1446 * struct {
1447 * u64 tm_tfhar;
1448 * u64 tm_texasr;
1449 * u64 tm_tfiar;
1450 * };
1451 */
1452static int tm_spr_get(struct task_struct *target,
1453 const struct user_regset *regset,
1454 unsigned int pos, unsigned int count,
1455 void *kbuf, void __user *ubuf)
1456{
1457 int ret;
1458
1459 /* Build tests */
1460 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
1461 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
1462 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
1463
1464 if (!cpu_has_feature(CPU_FTR_TM))
1465 return -ENODEV;
1466
1467 /* Flush the states */
1468 flush_fp_to_thread(target);
1469 flush_altivec_to_thread(target);
1470 flush_tmregs_to_thread(target);
1471
1472 /* TFHAR register */
1473 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
1474 &target->thread.tm_tfhar, 0, sizeof(u64));
1475
1476 /* TEXASR register */
1477 if (!ret)
1478 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
1479 &target->thread.tm_texasr, sizeof(u64),
1480 2 * sizeof(u64));
1481
1482 /* TFIAR register */
1483 if (!ret)
1484 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
1485 &target->thread.tm_tfiar,
1486 2 * sizeof(u64), 3 * sizeof(u64));
1487 return ret;
1488}
1489
1490/**
1491 * tm_spr_set - set the TM related SPR registers
1492 * @target: The target task.
1493 * @regset: The user regset structure.
1494 * @pos: The buffer position.
1495 * @count: Number of bytes to copy.
1496 * @kbuf: Kernel buffer to copy into.
1497 * @ubuf: User buffer to copy from.
1498 *
1499 * This function sets transactional memory related SPR registers.
1500 * The userspace interface buffer layout is as follows.
1501 *
1502 * struct {
1503 * u64 tm_tfhar;
1504 * u64 tm_texasr;
1505 * u64 tm_tfiar;
1506 * };
1507 */
1508static int tm_spr_set(struct task_struct *target,
1509 const struct user_regset *regset,
1510 unsigned int pos, unsigned int count,
1511 const void *kbuf, const void __user *ubuf)
1512{
1513 int ret;
1514
1515 /* Build tests */
1516 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
1517 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
1518 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
1519
1520 if (!cpu_has_feature(CPU_FTR_TM))
1521 return -ENODEV;
1522
1523 /* Flush the states */
1524 flush_fp_to_thread(target);
1525 flush_altivec_to_thread(target);
1526 flush_tmregs_to_thread(target);
1527
1528 /* TFHAR register */
1529 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1530 &target->thread.tm_tfhar, 0, sizeof(u64));
1531
1532 /* TEXASR register */
1533 if (!ret)
1534 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1535 &target->thread.tm_texasr, sizeof(u64),
1536 2 * sizeof(u64));
1537
1538 /* TFIAR register */
1539 if (!ret)
1540 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1541 &target->thread.tm_tfiar,
1542 2 * sizeof(u64), 3 * sizeof(u64));
1543 return ret;
1544}
1545#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
1416 1546
1417/* 1547/*
1418 * These are our native regset flavors. 1548 * These are our native regset flavors.
@@ -1434,6 +1564,7 @@ enum powerpc_regset {
1434 REGSET_TM_CFPR, /* TM checkpointed FPR registers */ 1564 REGSET_TM_CFPR, /* TM checkpointed FPR registers */
1435 REGSET_TM_CVMX, /* TM checkpointed VMX registers */ 1565 REGSET_TM_CVMX, /* TM checkpointed VMX registers */
1436 REGSET_TM_CVSX, /* TM checkpointed VSX registers */ 1566 REGSET_TM_CVSX, /* TM checkpointed VSX registers */
1567 REGSET_TM_SPR, /* TM specific SPR registers */
1437#endif 1568#endif
1438}; 1569};
1439 1570
@@ -1490,6 +1621,11 @@ static const struct user_regset native_regsets[] = {
1490 .size = sizeof(double), .align = sizeof(double), 1621 .size = sizeof(double), .align = sizeof(double),
1491 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set 1622 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
1492 }, 1623 },
1624 [REGSET_TM_SPR] = {
1625 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
1626 .size = sizeof(u64), .align = sizeof(u64),
1627 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
1628 },
1493#endif 1629#endif
1494}; 1630};
1495 1631
@@ -1737,6 +1873,11 @@ static const struct user_regset compat_regsets[] = {
1737 .size = sizeof(double), .align = sizeof(double), 1873 .size = sizeof(double), .align = sizeof(double),
1738 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set 1874 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
1739 }, 1875 },
1876 [REGSET_TM_SPR] = {
1877 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
1878 .size = sizeof(u64), .align = sizeof(u64),
1879 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
1880 },
1740#endif 1881#endif
1741}; 1882};
1742 1883