@@ -65,6 +65,7 @@ struct pt_regs_offset {
65
65
#define REG_OFFSET_END {.name = NULL, .offset = 0}
66
66
67
67
#define TVSO (f ) (offsetof(struct thread_vr_state, f))
68
+ #define TFSO (f ) (offsetof(struct thread_fp_state, f))
68
69
69
70
static const struct pt_regs_offset regoffset_table [] = {
70
71
GPR_OFFSET_NAME (0 ),
@@ -1294,6 +1295,123 @@ static int tm_cvmx_set(struct task_struct *target,
1294
1295
1295
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
+ */
1307
+ static 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
+ */
1340
+ static 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
+ */
1388
+ static 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
1415
#endif
1298
1416
1299
1417
/*
@@ -1315,6 +1433,7 @@ enum powerpc_regset {
1315
1433
REGSET_TM_CGPR , /* TM checkpointed GPR registers */
1316
1434
REGSET_TM_CFPR , /* TM checkpointed FPR registers */
1317
1435
REGSET_TM_CVMX , /* TM checkpointed VMX registers */
1436
+ REGSET_TM_CVSX , /* TM checkpointed VSX registers */
1318
1437
#endif
1319
1438
};
1320
1439
@@ -1366,6 +1485,11 @@ static const struct user_regset native_regsets[] = {
1366
1485
.size = sizeof (vector128 ), .align = sizeof (vector128 ),
1367
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
1493
#endif
1370
1494
};
1371
1495
@@ -1608,6 +1732,11 @@ static const struct user_regset compat_regsets[] = {
1608
1732
.size = sizeof (vector128 ), .align = sizeof (vector128 ),
1609
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
1740
#endif
1612
1741
};
1613
1742
0 commit comments