@@ -541,6 +541,60 @@ static int getregs64_get(struct task_struct *target,
541
541
return ret ;
542
542
}
543
543
544
+ static int setregs64_set (struct task_struct * target ,
545
+ const struct user_regset * regset ,
546
+ unsigned int pos , unsigned int count ,
547
+ const void * kbuf , const void __user * ubuf )
548
+ {
549
+ struct pt_regs * regs = task_pt_regs (target );
550
+ unsigned long y = regs -> y ;
551
+ unsigned long tstate ;
552
+ int ret ;
553
+
554
+ if (target == current )
555
+ flushw_user ();
556
+
557
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
558
+ regs -> u_regs + 1 ,
559
+ 0 * sizeof (u64 ),
560
+ 15 * sizeof (u64 ));
561
+ if (ret )
562
+ return ret ;
563
+ ret = user_regset_copyin_ignore (& pos , & count , & kbuf , & ubuf ,
564
+ 15 * sizeof (u64 ), 16 * sizeof (u64 ));
565
+ if (ret )
566
+ return ret ;
567
+ /* TSTATE */
568
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
569
+ & tstate ,
570
+ 16 * sizeof (u64 ),
571
+ 17 * sizeof (u64 ));
572
+ if (ret )
573
+ return ret ;
574
+ /* Only the condition codes and the "in syscall"
575
+ * state can be modified in the %tstate register.
576
+ */
577
+ tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL );
578
+ regs -> tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL );
579
+ regs -> tstate |= tstate ;
580
+
581
+ /* TPC, TNPC */
582
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
583
+ & regs -> tpc ,
584
+ 17 * sizeof (u64 ),
585
+ 19 * sizeof (u64 ));
586
+ if (ret )
587
+ return ret ;
588
+ /* Y */
589
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
590
+ & y ,
591
+ 19 * sizeof (u64 ),
592
+ 20 * sizeof (u64 ));
593
+ if (!ret )
594
+ regs -> y = y ;
595
+ return ret ;
596
+ }
597
+
544
598
static const struct user_regset ptrace64_regsets [] = {
545
599
/* Format is:
546
600
* G1 --> G7
@@ -549,7 +603,8 @@ static const struct user_regset ptrace64_regsets[] = {
549
603
* TSTATE, TPC, TNPC, Y
550
604
*/
551
605
[REGSET_GENERAL ] = {
552
- .n = 20 , .size = sizeof (u64 ), .get = getregs64_get ,
606
+ .n = 20 , .size = sizeof (u64 ),
607
+ .get = getregs64_get , .set = setregs64_set ,
553
608
},
554
609
};
555
610
@@ -914,6 +969,40 @@ static int getregs_get(struct task_struct *target,
914
969
0 , 19 * sizeof (u32 ));
915
970
}
916
971
972
+ static int setregs_set (struct task_struct * target ,
973
+ const struct user_regset * regset ,
974
+ unsigned int pos , unsigned int count ,
975
+ const void * kbuf , const void __user * ubuf )
976
+ {
977
+ struct pt_regs * regs = task_pt_regs (target );
978
+ unsigned long tstate ;
979
+ u32 uregs [19 ];
980
+ int i , ret ;
981
+
982
+ if (target == current )
983
+ flushw_user ();
984
+
985
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
986
+ uregs ,
987
+ 0 , 19 * sizeof (u32 ));
988
+ if (ret )
989
+ return ret ;
990
+
991
+ tstate = regs -> tstate ;
992
+ tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL );
993
+ tstate |= psr_to_tstate_icc (uregs [0 ]);
994
+ if (uregs [0 ] & PSR_SYSCALL )
995
+ tstate |= TSTATE_SYSCALL ;
996
+ regs -> tstate = tstate ;
997
+ regs -> tpc = uregs [1 ];
998
+ regs -> tnpc = uregs [2 ];
999
+ regs -> y = uregs [3 ];
1000
+
1001
+ for (i = 1 ; i < 15 ; i ++ )
1002
+ regs -> u_regs [i ] = uregs [3 + i ];
1003
+ return 0 ;
1004
+ }
1005
+
917
1006
static int getfpregs_get (struct task_struct * target ,
918
1007
const struct user_regset * regset ,
919
1008
unsigned int pos , unsigned int count ,
@@ -948,12 +1037,52 @@ static int getfpregs_get(struct task_struct *target,
948
1037
return ret ;
949
1038
}
950
1039
1040
+ static int setfpregs_set (struct task_struct * target ,
1041
+ const struct user_regset * regset ,
1042
+ unsigned int pos , unsigned int count ,
1043
+ const void * kbuf , const void __user * ubuf )
1044
+ {
1045
+ unsigned long * fpregs = task_thread_info (target )-> fpregs ;
1046
+ unsigned long fprs ;
1047
+ int ret ;
1048
+
1049
+ if (target == current )
1050
+ save_and_clear_fpu ();
1051
+
1052
+ fprs = task_thread_info (target )-> fpsaved [0 ];
1053
+
1054
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
1055
+ fpregs ,
1056
+ 0 , 32 * sizeof (u32 ));
1057
+ if (!ret ) {
1058
+ compat_ulong_t fsr ;
1059
+ unsigned long val ;
1060
+
1061
+ ret = user_regset_copyin (& pos , & count , & kbuf , & ubuf ,
1062
+ & fsr ,
1063
+ 32 * sizeof (u32 ),
1064
+ 33 * sizeof (u32 ));
1065
+ if (!ret ) {
1066
+ val = task_thread_info (target )-> xfsr [0 ];
1067
+ val &= 0xffffffff00000000UL ;
1068
+ val |= fsr ;
1069
+ task_thread_info (target )-> xfsr [0 ] = val ;
1070
+ }
1071
+ }
1072
+
1073
+ fprs |= (FPRS_FEF | FPRS_DL );
1074
+ task_thread_info (target )-> fpsaved [0 ] = fprs ;
1075
+ return ret ;
1076
+ }
1077
+
951
1078
static const struct user_regset ptrace32_regsets [] = {
952
1079
[REGSET_GENERAL ] = {
953
- .n = 19 , .size = sizeof (u32 ), .get = getregs_get ,
1080
+ .n = 19 , .size = sizeof (u32 ),
1081
+ .get = getregs_get , .set = setregs_set ,
954
1082
},
955
1083
[REGSET_FP ] = {
956
- .n = 68 , .size = sizeof (u32 ), .get = getfpregs_get ,
1084
+ .n = 68 , .size = sizeof (u32 ),
1085
+ .get = getfpregs_get , .set = setfpregs_set ,
957
1086
},
958
1087
};
959
1088
@@ -992,7 +1121,6 @@ struct compat_fps {
992
1121
long compat_arch_ptrace (struct task_struct * child , compat_long_t request ,
993
1122
compat_ulong_t caddr , compat_ulong_t cdata )
994
1123
{
995
- const struct user_regset_view * view = task_user_regset_view (current );
996
1124
compat_ulong_t caddr2 = task_pt_regs (current )-> u_regs [UREG_I4 ];
997
1125
struct pt_regs32 __user * pregs ;
998
1126
struct compat_fps __user * fps ;
@@ -1017,15 +1145,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
1017
1145
break ;
1018
1146
1019
1147
case PTRACE_SETREGS :
1020
- ret = copy_regset_from_user (child , view , REGSET_GENERAL ,
1021
- 32 * sizeof (u32 ),
1022
- 4 * sizeof (u32 ),
1023
- & pregs -> psr );
1024
- if (!ret )
1025
- ret = copy_regset_from_user (child , view , REGSET_GENERAL ,
1026
- 1 * sizeof (u32 ),
1027
- 15 * sizeof (u32 ),
1028
- & pregs -> u_regs [0 ]);
1148
+ ret = copy_regset_from_user (child , & ptrace32_view ,
1149
+ REGSET_GENERAL , 0 ,
1150
+ 19 * sizeof (u32 ),
1151
+ pregs );
1029
1152
break ;
1030
1153
1031
1154
case PTRACE_GETFPREGS :
@@ -1036,15 +1159,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
1036
1159
break ;
1037
1160
1038
1161
case PTRACE_SETFPREGS :
1039
- ret = copy_regset_from_user (child , view , REGSET_FP ,
1040
- 0 * sizeof (u32 ),
1041
- 32 * sizeof (u32 ),
1042
- & fps -> regs [0 ]);
1043
- if (!ret )
1044
- ret = copy_regset_from_user (child , view , REGSET_FP ,
1045
- 33 * sizeof (u32 ),
1046
- 1 * sizeof (u32 ),
1047
- & fps -> fsr );
1162
+ ret = copy_regset_from_user (child , & ptrace32_view ,
1163
+ REGSET_FP , 0 ,
1164
+ 33 * sizeof (u32 ),
1165
+ fps );
1048
1166
break ;
1049
1167
1050
1168
case PTRACE_READTEXT :
@@ -1110,17 +1228,10 @@ long arch_ptrace(struct task_struct *child, long request,
1110
1228
break ;
1111
1229
1112
1230
case PTRACE_SETREGS64 :
1113
- ret = copy_regset_from_user (child , view , REGSET_GENERAL ,
1114
- 1 * sizeof (u64 ),
1115
- 15 * sizeof (u64 ),
1116
- & pregs -> u_regs [0 ]);
1117
- if (!ret ) {
1118
- /* XXX doesn't handle 'y' register correctly XXX */
1119
- ret = copy_regset_from_user (child , view , REGSET_GENERAL ,
1120
- 32 * sizeof (u64 ),
1121
- 4 * sizeof (u64 ),
1122
- & pregs -> tstate );
1123
- }
1231
+ ret = copy_regset_from_user (child , & ptrace64_view ,
1232
+ REGSET_GENERAL , 0 ,
1233
+ 19 * sizeof (u64 ),
1234
+ pregs );
1124
1235
break ;
1125
1236
1126
1237
case PTRACE_GETFPREGS64 :
0 commit comments