aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/ptrace.c')
-rw-r--r--arch/s390/kernel/ptrace.c115
1 files changed, 83 insertions, 32 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 99a567b70d16..eabfb4594517 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -248,14 +248,27 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
248 */ 248 */
249 tmp = 0; 249 tmp = 0;
250 250
251 } else if (addr == (addr_t) &dummy->regs.fp_regs.fpc) {
252 /*
253 * floating point control reg. is in the thread structure
254 */
255 tmp = child->thread.fp_regs.fpc;
256 tmp <<= BITS_PER_LONG - 32;
257
251 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { 258 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
252 /* 259 /*
253 * floating point regs. are stored in the thread structure 260 * floating point regs. are either in child->thread.fp_regs
261 * or the child->thread.vxrs array
254 */ 262 */
255 offset = addr - (addr_t) &dummy->regs.fp_regs; 263 offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
256 tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset); 264#ifdef CONFIG_64BIT
257 if (addr == (addr_t) &dummy->regs.fp_regs.fpc) 265 if (child->thread.vxrs)
258 tmp <<= BITS_PER_LONG - 32; 266 tmp = *(addr_t *)
267 ((addr_t) child->thread.vxrs + 2*offset);
268 else
269#endif
270 tmp = *(addr_t *)
271 ((addr_t) &child->thread.fp_regs.fprs + offset);
259 272
260 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { 273 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
261 /* 274 /*
@@ -383,16 +396,29 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
383 */ 396 */
384 return 0; 397 return 0;
385 398
399 } else if (addr == (addr_t) &dummy->regs.fp_regs.fpc) {
400 /*
401 * floating point control reg. is in the thread structure
402 */
403 if ((unsigned int) data != 0 ||
404 test_fp_ctl(data >> (BITS_PER_LONG - 32)))
405 return -EINVAL;
406 child->thread.fp_regs.fpc = data >> (BITS_PER_LONG - 32);
407
386 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { 408 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
387 /* 409 /*
388 * floating point regs. are stored in the thread structure 410 * floating point regs. are either in child->thread.fp_regs
411 * or the child->thread.vxrs array
389 */ 412 */
390 if (addr == (addr_t) &dummy->regs.fp_regs.fpc) 413 offset = addr - (addr_t) &dummy->regs.fp_regs.fprs;
391 if ((unsigned int) data != 0 || 414#ifdef CONFIG_64BIT
392 test_fp_ctl(data >> (BITS_PER_LONG - 32))) 415 if (child->thread.vxrs)
393 return -EINVAL; 416 *(addr_t *)((addr_t)
394 offset = addr - (addr_t) &dummy->regs.fp_regs; 417 child->thread.vxrs + 2*offset) = data;
395 *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data; 418 else
419#endif
420 *(addr_t *)((addr_t)
421 &child->thread.fp_regs.fprs + offset) = data;
396 422
397 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { 423 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
398 /* 424 /*
@@ -611,12 +637,26 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
611 */ 637 */
612 tmp = 0; 638 tmp = 0;
613 639
640 } else if (addr == (addr_t) &dummy32->regs.fp_regs.fpc) {
641 /*
642 * floating point control reg. is in the thread structure
643 */
644 tmp = child->thread.fp_regs.fpc;
645
614 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { 646 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
615 /* 647 /*
616 * floating point regs. are stored in the thread structure 648 * floating point regs. are either in child->thread.fp_regs
649 * or the child->thread.vxrs array
617 */ 650 */
618 offset = addr - (addr_t) &dummy32->regs.fp_regs; 651 offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
619 tmp = *(__u32 *)((addr_t) &child->thread.fp_regs + offset); 652#ifdef CONFIG_64BIT
653 if (child->thread.vxrs)
654 tmp = *(__u32 *)
655 ((addr_t) child->thread.vxrs + 2*offset);
656 else
657#endif
658 tmp = *(__u32 *)
659 ((addr_t) &child->thread.fp_regs.fprs + offset);
620 660
621 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { 661 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
622 /* 662 /*
@@ -722,15 +762,28 @@ static int __poke_user_compat(struct task_struct *child,
722 */ 762 */
723 return 0; 763 return 0;
724 764
725 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { 765 } else if (addr == (addr_t) &dummy32->regs.fp_regs.fpc) {
726 /* 766 /*
727 * floating point regs. are stored in the thread structure 767 * floating point control reg. is in the thread structure
728 */ 768 */
729 if (addr == (addr_t) &dummy32->regs.fp_regs.fpc && 769 if (test_fp_ctl(tmp))
730 test_fp_ctl(tmp))
731 return -EINVAL; 770 return -EINVAL;
732 offset = addr - (addr_t) &dummy32->regs.fp_regs; 771 child->thread.fp_regs.fpc = data;
733 *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp; 772
773 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
774 /*
775 * floating point regs. are either in child->thread.fp_regs
776 * or the child->thread.vxrs array
777 */
778 offset = addr - (addr_t) &dummy32->regs.fp_regs.fprs;
779#ifdef CONFIG_64BIT
780 if (child->thread.vxrs)
781 *(__u32 *)((addr_t)
782 child->thread.vxrs + 2*offset) = tmp;
783 else
784#endif
785 *(__u32 *)((addr_t)
786 &child->thread.fp_regs.fprs + offset) = tmp;
734 787
735 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { 788 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
736 /* 789 /*
@@ -1038,12 +1091,6 @@ static int s390_tdb_set(struct task_struct *target,
1038 return 0; 1091 return 0;
1039} 1092}
1040 1093
1041static int s390_vxrs_active(struct task_struct *target,
1042 const struct user_regset *regset)
1043{
1044 return !!target->thread.vxrs;
1045}
1046
1047static int s390_vxrs_low_get(struct task_struct *target, 1094static int s390_vxrs_low_get(struct task_struct *target,
1048 const struct user_regset *regset, 1095 const struct user_regset *regset,
1049 unsigned int pos, unsigned int count, 1096 unsigned int pos, unsigned int count,
@@ -1052,6 +1099,8 @@ static int s390_vxrs_low_get(struct task_struct *target,
1052 __u64 vxrs[__NUM_VXRS_LOW]; 1099 __u64 vxrs[__NUM_VXRS_LOW];
1053 int i; 1100 int i;
1054 1101
1102 if (!MACHINE_HAS_VX)
1103 return -ENODEV;
1055 if (target->thread.vxrs) { 1104 if (target->thread.vxrs) {
1056 if (target == current) 1105 if (target == current)
1057 save_vx_regs(target->thread.vxrs); 1106 save_vx_regs(target->thread.vxrs);
@@ -1070,6 +1119,8 @@ static int s390_vxrs_low_set(struct task_struct *target,
1070 __u64 vxrs[__NUM_VXRS_LOW]; 1119 __u64 vxrs[__NUM_VXRS_LOW];
1071 int i, rc; 1120 int i, rc;
1072 1121
1122 if (!MACHINE_HAS_VX)
1123 return -ENODEV;
1073 if (!target->thread.vxrs) { 1124 if (!target->thread.vxrs) {
1074 rc = alloc_vector_registers(target); 1125 rc = alloc_vector_registers(target);
1075 if (rc) 1126 if (rc)
@@ -1095,6 +1146,8 @@ static int s390_vxrs_high_get(struct task_struct *target,
1095{ 1146{
1096 __vector128 vxrs[__NUM_VXRS_HIGH]; 1147 __vector128 vxrs[__NUM_VXRS_HIGH];
1097 1148
1149 if (!MACHINE_HAS_VX)
1150 return -ENODEV;
1098 if (target->thread.vxrs) { 1151 if (target->thread.vxrs) {
1099 if (target == current) 1152 if (target == current)
1100 save_vx_regs(target->thread.vxrs); 1153 save_vx_regs(target->thread.vxrs);
@@ -1112,6 +1165,8 @@ static int s390_vxrs_high_set(struct task_struct *target,
1112{ 1165{
1113 int rc; 1166 int rc;
1114 1167
1168 if (!MACHINE_HAS_VX)
1169 return -ENODEV;
1115 if (!target->thread.vxrs) { 1170 if (!target->thread.vxrs) {
1116 rc = alloc_vector_registers(target); 1171 rc = alloc_vector_registers(target);
1117 if (rc) 1172 if (rc)
@@ -1196,7 +1251,6 @@ static const struct user_regset s390_regsets[] = {
1196 .n = __NUM_VXRS_LOW, 1251 .n = __NUM_VXRS_LOW,
1197 .size = sizeof(__u64), 1252 .size = sizeof(__u64),
1198 .align = sizeof(__u64), 1253 .align = sizeof(__u64),
1199 .active = s390_vxrs_active,
1200 .get = s390_vxrs_low_get, 1254 .get = s390_vxrs_low_get,
1201 .set = s390_vxrs_low_set, 1255 .set = s390_vxrs_low_set,
1202 }, 1256 },
@@ -1205,7 +1259,6 @@ static const struct user_regset s390_regsets[] = {
1205 .n = __NUM_VXRS_HIGH, 1259 .n = __NUM_VXRS_HIGH,
1206 .size = sizeof(__vector128), 1260 .size = sizeof(__vector128),
1207 .align = sizeof(__vector128), 1261 .align = sizeof(__vector128),
1208 .active = s390_vxrs_active,
1209 .get = s390_vxrs_high_get, 1262 .get = s390_vxrs_high_get,
1210 .set = s390_vxrs_high_set, 1263 .set = s390_vxrs_high_set,
1211 }, 1264 },
@@ -1419,7 +1472,6 @@ static const struct user_regset s390_compat_regsets[] = {
1419 .n = __NUM_VXRS_LOW, 1472 .n = __NUM_VXRS_LOW,
1420 .size = sizeof(__u64), 1473 .size = sizeof(__u64),
1421 .align = sizeof(__u64), 1474 .align = sizeof(__u64),
1422 .active = s390_vxrs_active,
1423 .get = s390_vxrs_low_get, 1475 .get = s390_vxrs_low_get,
1424 .set = s390_vxrs_low_set, 1476 .set = s390_vxrs_low_set,
1425 }, 1477 },
@@ -1428,7 +1480,6 @@ static const struct user_regset s390_compat_regsets[] = {
1428 .n = __NUM_VXRS_HIGH, 1480 .n = __NUM_VXRS_HIGH,
1429 .size = sizeof(__vector128), 1481 .size = sizeof(__vector128),
1430 .align = sizeof(__vector128), 1482 .align = sizeof(__vector128),
1431 .active = s390_vxrs_active,
1432 .get = s390_vxrs_high_get, 1483 .get = s390_vxrs_high_get,
1433 .set = s390_vxrs_high_set, 1484 .set = s390_vxrs_high_set,
1434 }, 1485 },