aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnshuman Khandual <khandual@linux.vnet.ibm.com>2016-07-27 22:57:39 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-07-31 21:15:20 -0400
commit9d3918f7c0e516bb8782915cdb2f8cbdbf6c4f9b (patch)
treec90e9e05fc25c8ffb45583ae95be956b767e94be
parent8c13f5999997d36fc5fb296809efedc13c801704 (diff)
powerpc/ptrace: Enable support for NT_PPC_CVSX
This patch enables support for TM checkpointed VSX register set ELF core note NT_PPC_CVSX based ptrace requests through PTRACE_GETREGSET, PTRACE_SETREGSET calls. This is achieved through adding a register set REGSET_CVSX 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.c129
2 files changed, 130 insertions, 0 deletions
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index ecb4e84cb22c..1549172aa258 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -92,6 +92,7 @@
92#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ 92#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
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 96
96typedef unsigned long elf_greg_t64; 97typedef unsigned long elf_greg_t64;
97typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; 98typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 6e42137c0175..df6afe7da4da 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -65,6 +65,7 @@ struct pt_regs_offset {
65#define REG_OFFSET_END {.name = NULL, .offset = 0} 65#define REG_OFFSET_END {.name = NULL, .offset = 0}
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 69
69static const struct pt_regs_offset regoffset_table[] = { 70static const struct pt_regs_offset regoffset_table[] = {
70 GPR_OFFSET_NAME(0), 71 GPR_OFFSET_NAME(0),
@@ -1294,6 +1295,123 @@ static int tm_cvmx_set(struct task_struct *target,
1294 1295
1295 return ret; 1296 return ret;
1296} 1297}
1298
1299/**
1300 * tm_cvsx_active - get active number of registers in CVSX
1301 * @target: The target task.
1302 * @regset: The user regset structure.
1303 *
1304 * This function checks for the active number of available
1305 * regisers in transaction checkpointed VSX category.
1306 */
1307static int tm_cvsx_active(struct task_struct *target,
1308 const struct user_regset *regset)
1309{
1310 if (!cpu_has_feature(CPU_FTR_TM))
1311 return -ENODEV;
1312
1313 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
1314 return 0;
1315
1316 flush_vsx_to_thread(target);
1317 return target->thread.used_vsr ? regset->n : 0;
1318}
1319
1320/**
1321 * tm_cvsx_get - get CVSX registers
1322 * @target: The target task.
1323 * @regset: The user regset structure.
1324 * @pos: The buffer position.
1325 * @count: Number of bytes to copy.
1326 * @kbuf: Kernel buffer to copy from.
1327 * @ubuf: User buffer to copy into.
1328 *
1329 * This function gets in transaction checkpointed VSX registers.
1330 *
1331 * When the transaction is active 'fp_state' holds the checkpointed
1332 * values for the current transaction to fall back on if it aborts
1333 * in between. This function gets those checkpointed VSX registers.
1334 * The userspace interface buffer layout is as follows.
1335 *
1336 * struct data {
1337 * u64 vsx[32];
1338 *};
1339 */
1340static int tm_cvsx_get(struct task_struct *target,
1341 const struct user_regset *regset,
1342 unsigned int pos, unsigned int count,
1343 void *kbuf, void __user *ubuf)
1344{
1345 u64 buf[32];
1346 int ret, i;
1347
1348 if (!cpu_has_feature(CPU_FTR_TM))
1349 return -ENODEV;
1350
1351 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
1352 return -ENODATA;
1353
1354 /* Flush the state */
1355 flush_fp_to_thread(target);
1356 flush_altivec_to_thread(target);
1357 flush_tmregs_to_thread(target);
1358 flush_vsx_to_thread(target);
1359
1360 for (i = 0; i < 32 ; i++)
1361 buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
1362 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
1363 buf, 0, 32 * sizeof(double));
1364
1365 return ret;
1366}
1367
1368/**
1369 * tm_cvsx_set - set CFPR registers
1370 * @target: The target task.
1371 * @regset: The user regset structure.
1372 * @pos: The buffer position.
1373 * @count: Number of bytes to copy.
1374 * @kbuf: Kernel buffer to copy into.
1375 * @ubuf: User buffer to copy from.
1376 *
1377 * This function sets in transaction checkpointed VSX registers.
1378 *
1379 * When the transaction is active 'fp_state' holds the checkpointed
1380 * VSX register values for the current transaction to fall back on
1381 * if it aborts in between. This function sets these checkpointed
1382 * FPR registers. The userspace interface buffer layout is as follows.
1383 *
1384 * struct data {
1385 * u64 vsx[32];
1386 *};
1387 */
1388static int tm_cvsx_set(struct task_struct *target,
1389 const struct user_regset *regset,
1390 unsigned int pos, unsigned int count,
1391 const void *kbuf, const void __user *ubuf)
1392{
1393 u64 buf[32];
1394 int ret, i;
1395
1396 if (!cpu_has_feature(CPU_FTR_TM))
1397 return -ENODEV;
1398
1399 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
1400 return -ENODATA;
1401
1402 /* Flush the state */
1403 flush_fp_to_thread(target);
1404 flush_altivec_to_thread(target);
1405 flush_tmregs_to_thread(target);
1406 flush_vsx_to_thread(target);
1407
1408 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1409 buf, 0, 32 * sizeof(double));
1410 for (i = 0; i < 32 ; i++)
1411 target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
1412
1413 return ret;
1414}
1297#endif 1415#endif
1298 1416
1299/* 1417/*
@@ -1315,6 +1433,7 @@ enum powerpc_regset {
1315 REGSET_TM_CGPR, /* TM checkpointed GPR registers */ 1433 REGSET_TM_CGPR, /* TM checkpointed GPR registers */
1316 REGSET_TM_CFPR, /* TM checkpointed FPR registers */ 1434 REGSET_TM_CFPR, /* TM checkpointed FPR registers */
1317 REGSET_TM_CVMX, /* TM checkpointed VMX registers */ 1435 REGSET_TM_CVMX, /* TM checkpointed VMX registers */
1436 REGSET_TM_CVSX, /* TM checkpointed VSX registers */
1318#endif 1437#endif
1319}; 1438};
1320 1439
@@ -1366,6 +1485,11 @@ static const struct user_regset native_regsets[] = {
1366 .size = sizeof(vector128), .align = sizeof(vector128), 1485 .size = sizeof(vector128), .align = sizeof(vector128),
1367 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set 1486 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
1368 }, 1487 },
1488 [REGSET_TM_CVSX] = {
1489 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
1490 .size = sizeof(double), .align = sizeof(double),
1491 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
1492 },
1369#endif 1493#endif
1370}; 1494};
1371 1495
@@ -1608,6 +1732,11 @@ static const struct user_regset compat_regsets[] = {
1608 .size = sizeof(vector128), .align = sizeof(vector128), 1732 .size = sizeof(vector128), .align = sizeof(vector128),
1609 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set 1733 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
1610 }, 1734 },
1735 [REGSET_TM_CVSX] = {
1736 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
1737 .size = sizeof(double), .align = sizeof(double),
1738 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
1739 },
1611#endif 1740#endif
1612}; 1741};
1613 1742