Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/ptrace: add runtime instrumention register get/set

Add runtime instrumention register get and set which allows to read
and modify the runtime instrumention control block.

Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Alice Frosi and committed by
Martin Schwidefsky
262832bc bb59c2da

+110
+109
arch/s390/kernel/ptrace.c
··· 30 30 #include <linux/uaccess.h> 31 31 #include <asm/unistd.h> 32 32 #include <asm/switch_to.h> 33 + #include <asm/runtime_instr.h> 34 + #include <asm/facility.h> 35 + 33 36 #include "entry.h" 34 37 35 38 #ifdef CONFIG_COMPAT ··· 1242 1239 data, 0, sizeof(struct gs_cb)); 1243 1240 } 1244 1241 1242 + static bool is_ri_cb_valid(struct runtime_instr_cb *cb) 1243 + { 1244 + return (cb->rca & 0x1f) == 0 && 1245 + (cb->roa & 0xfff) == 0 && 1246 + (cb->rla & 0xfff) == 0xfff && 1247 + cb->s == 1 && 1248 + cb->k == 1 && 1249 + cb->h == 0 && 1250 + cb->reserved1 == 0 && 1251 + cb->ps == 1 && 1252 + cb->qs == 0 && 1253 + cb->pc == 1 && 1254 + cb->qc == 0 && 1255 + cb->reserved2 == 0 && 1256 + cb->key == PAGE_DEFAULT_KEY && 1257 + cb->reserved3 == 0 && 1258 + cb->reserved4 == 0 && 1259 + cb->reserved5 == 0 && 1260 + cb->reserved6 == 0 && 1261 + cb->reserved7 == 0 && 1262 + cb->reserved8 == 0 && 1263 + cb->rla >= cb->roa && 1264 + cb->rca >= cb->roa && 1265 + cb->rca <= cb->rla+1 && 1266 + cb->m < 3; 1267 + } 1268 + 1269 + static int s390_runtime_instr_get(struct task_struct *target, 1270 + const struct user_regset *regset, 1271 + unsigned int pos, unsigned int count, 1272 + void *kbuf, void __user *ubuf) 1273 + { 1274 + struct runtime_instr_cb *data = target->thread.ri_cb; 1275 + 1276 + if (!test_facility(64)) 1277 + return -ENODEV; 1278 + if (!data) 1279 + return -ENODATA; 1280 + 1281 + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 1282 + data, 0, sizeof(struct runtime_instr_cb)); 1283 + } 1284 + 1285 + static int s390_runtime_instr_set(struct task_struct *target, 1286 + const struct user_regset *regset, 1287 + unsigned int pos, unsigned int count, 1288 + const void *kbuf, const void __user *ubuf) 1289 + { 1290 + struct runtime_instr_cb ri_cb = { }, *data = NULL; 1291 + int rc; 1292 + 1293 + if (!test_facility(64)) 1294 + return -ENODEV; 1295 + 1296 + if (!target->thread.ri_cb) { 1297 + data = kzalloc(sizeof(*data), GFP_KERNEL); 1298 + if (!data) 1299 + return -ENOMEM; 1300 + } 1301 + 1302 + if (target->thread.ri_cb) { 1303 + if (target == current) 1304 + store_runtime_instr_cb(&ri_cb); 1305 + else 1306 + ri_cb = *target->thread.ri_cb; 1307 + } 1308 + 1309 + rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 1310 + &ri_cb, 0, sizeof(struct runtime_instr_cb)); 1311 + if (rc) { 1312 + kfree(data); 1313 + return -EFAULT; 1314 + } 1315 + 1316 + if (!is_ri_cb_valid(&ri_cb)) { 1317 + kfree(data); 1318 + return -EINVAL; 1319 + } 1320 + 1321 + preempt_disable(); 1322 + if (!target->thread.ri_cb) 1323 + target->thread.ri_cb = data; 1324 + *target->thread.ri_cb = ri_cb; 1325 + if (target == current) 1326 + load_runtime_instr_cb(target->thread.ri_cb); 1327 + preempt_enable(); 1328 + 1329 + return 0; 1330 + } 1331 + 1245 1332 static const struct user_regset s390_regsets[] = { 1246 1333 { 1247 1334 .core_note_type = NT_PRSTATUS, ··· 1404 1311 .align = sizeof(__u64), 1405 1312 .get = s390_gs_bc_get, 1406 1313 .set = s390_gs_bc_set, 1314 + }, 1315 + { 1316 + .core_note_type = NT_S390_RI_CB, 1317 + .n = sizeof(struct runtime_instr_cb) / sizeof(__u64), 1318 + .size = sizeof(__u64), 1319 + .align = sizeof(__u64), 1320 + .get = s390_runtime_instr_get, 1321 + .set = s390_runtime_instr_set, 1407 1322 }, 1408 1323 }; 1409 1324 ··· 1648 1547 .align = sizeof(__u64), 1649 1548 .get = s390_gs_cb_get, 1650 1549 .set = s390_gs_cb_set, 1550 + }, 1551 + { 1552 + .core_note_type = NT_S390_RI_CB, 1553 + .n = sizeof(struct runtime_instr_cb) / sizeof(__u64), 1554 + .size = sizeof(__u64), 1555 + .align = sizeof(__u64), 1556 + .get = s390_runtime_instr_get, 1557 + .set = s390_runtime_instr_set, 1651 1558 }, 1652 1559 }; 1653 1560
+1
include/uapi/linux/elf.h
··· 411 411 #define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ 412 412 #define NT_S390_GS_CB 0x30b /* s390 guarded storage registers */ 413 413 #define NT_S390_GS_BC 0x30c /* s390 guarded storage broadcast control block */ 414 + #define NT_S390_RI_CB 0x30d /* s390 runtime instrumentation */ 414 415 #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ 415 416 #define NT_ARM_TLS 0x401 /* ARM TLS register */ 416 417 #define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */