@@ -1009,32 +1009,20 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
1009
1009
return true;
1010
1010
}
1011
1011
1012
- static void fill_gap (unsigned to , void * * kbuf , unsigned * pos , unsigned * count )
1012
+ static void fill_gap (struct membuf * to , unsigned * last , unsigned offset )
1013
1013
{
1014
- if (* pos < to ) {
1015
- unsigned size = to - * pos ;
1016
-
1017
- if (size > * count )
1018
- size = * count ;
1019
- memcpy (* kbuf , (void * )& init_fpstate .xsave + * pos , size );
1020
- * kbuf += size ;
1021
- * pos += size ;
1022
- * count -= size ;
1023
- }
1014
+ if (* last >= offset )
1015
+ return ;
1016
+ membuf_write (to , (void * )& init_fpstate .xsave + * last , offset - * last );
1017
+ * last = offset ;
1024
1018
}
1025
1019
1026
- static void copy_part (unsigned offset , unsigned size , void * from ,
1027
- void * * kbuf , unsigned * pos , unsigned * count )
1020
+ static void copy_part (struct membuf * to , unsigned * last , unsigned offset ,
1021
+ unsigned size , void * from )
1028
1022
{
1029
- fill_gap (offset , kbuf , pos , count );
1030
- if (size > * count )
1031
- size = * count ;
1032
- if (size ) {
1033
- memcpy (* kbuf , from , size );
1034
- * kbuf += size ;
1035
- * pos += size ;
1036
- * count -= size ;
1037
- }
1023
+ fill_gap (to , last , offset );
1024
+ membuf_write (to , from , size );
1025
+ * last = offset + size ;
1038
1026
}
1039
1027
1040
1028
/*
@@ -1044,19 +1032,14 @@ static void copy_part(unsigned offset, unsigned size, void *from,
1044
1032
* It supports partial copy but pos always starts from zero. This is called
1045
1033
* from xstateregs_get() and there we check the CPU has XSAVES.
1046
1034
*/
1047
- int copy_xstate_to_kernel (void * kbuf , struct xregs_state * xsave , unsigned int offset_start , unsigned int size_total )
1035
+ void copy_xstate_to_kernel (struct membuf to , struct xregs_state * xsave )
1048
1036
{
1049
1037
struct xstate_header header ;
1050
1038
const unsigned off_mxcsr = offsetof(struct fxregs_state , mxcsr );
1051
- unsigned count = size_total ;
1039
+ unsigned size = to .left ;
1040
+ unsigned last = 0 ;
1052
1041
int i ;
1053
1042
1054
- /*
1055
- * Currently copy_regset_to_user() starts from pos 0:
1056
- */
1057
- if (unlikely (offset_start != 0 ))
1058
- return - EFAULT ;
1059
-
1060
1043
/*
1061
1044
* The destination is a ptrace buffer; we put in only user xstates:
1062
1045
*/
@@ -1065,27 +1048,26 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
1065
1048
header .xfeatures &= xfeatures_mask_user ();
1066
1049
1067
1050
if (header .xfeatures & XFEATURE_MASK_FP )
1068
- copy_part (0 , off_mxcsr ,
1069
- & xsave -> i387 , & kbuf , & offset_start , & count );
1051
+ copy_part (& to , & last , 0 , off_mxcsr , & xsave -> i387 );
1070
1052
if (header .xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM ))
1071
- copy_part (off_mxcsr , MXCSR_AND_FLAGS_SIZE ,
1072
- & xsave -> i387 .mxcsr , & kbuf , & offset_start , & count );
1053
+ copy_part (& to , & last , off_mxcsr ,
1054
+ MXCSR_AND_FLAGS_SIZE , & xsave -> i387 .mxcsr );
1073
1055
if (header .xfeatures & XFEATURE_MASK_FP )
1074
- copy_part (offsetof(struct fxregs_state , st_space ), 128 ,
1075
- & xsave -> i387 .st_space , & kbuf , & offset_start , & count );
1056
+ copy_part (& to , & last , offsetof(struct fxregs_state , st_space ),
1057
+ 128 , & xsave -> i387 .st_space );
1076
1058
if (header .xfeatures & XFEATURE_MASK_SSE )
1077
- copy_part (xstate_offsets [XFEATURE_MASK_SSE ], 256 ,
1078
- & xsave -> i387 .xmm_space , & kbuf , & offset_start , & count );
1059
+ copy_part (& to , & last , xstate_offsets [XFEATURE_SSE ] ,
1060
+ 256 , & xsave -> i387 .xmm_space );
1079
1061
/*
1080
1062
* Fill xsave->i387.sw_reserved value for ptrace frame:
1081
1063
*/
1082
- copy_part (offsetof(struct fxregs_state , sw_reserved ), 48 ,
1083
- xstate_fx_sw_bytes , & kbuf , & offset_start , & count );
1064
+ copy_part (& to , & last , offsetof(struct fxregs_state , sw_reserved ),
1065
+ 48 , xstate_fx_sw_bytes );
1084
1066
/*
1085
1067
* Copy xregs_state->header:
1086
1068
*/
1087
- copy_part (offsetof(struct xregs_state , header ), sizeof ( header ),
1088
- & header , & kbuf , & offset_start , & count );
1069
+ copy_part (& to , & last , offsetof(struct xregs_state , header ),
1070
+ sizeof ( header ) , & header );
1089
1071
1090
1072
for (i = FIRST_EXTENDED_XFEATURE ; i < XFEATURE_MAX ; i ++ ) {
1091
1073
/*
@@ -1094,104 +1076,12 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
1094
1076
if ((header .xfeatures >> i ) & 1 ) {
1095
1077
void * src = __raw_xsave_addr (xsave , i );
1096
1078
1097
- copy_part (xstate_offsets [ i ], xstate_sizes [i ],
1098
- src , & kbuf , & offset_start , & count );
1079
+ copy_part (& to , & last , xstate_offsets [i ],
1080
+ xstate_sizes [ i ], src );
1099
1081
}
1100
1082
1101
1083
}
1102
- fill_gap (size_total , & kbuf , & offset_start , & count );
1103
-
1104
- return 0 ;
1105
- }
1106
-
1107
- static inline int
1108
- __copy_xstate_to_user (void __user * ubuf , const void * data , unsigned int offset , unsigned int size , unsigned int size_total )
1109
- {
1110
- if (!size )
1111
- return 0 ;
1112
-
1113
- if (offset < size_total ) {
1114
- unsigned int copy = min (size , size_total - offset );
1115
-
1116
- if (__copy_to_user (ubuf + offset , data , copy ))
1117
- return - EFAULT ;
1118
- }
1119
- return 0 ;
1120
- }
1121
-
1122
- /*
1123
- * Convert from kernel XSAVES compacted format to standard format and copy
1124
- * to a user-space buffer. It supports partial copy but pos always starts from
1125
- * zero. This is called from xstateregs_get() and there we check the CPU
1126
- * has XSAVES.
1127
- */
1128
- int copy_xstate_to_user (void __user * ubuf , struct xregs_state * xsave , unsigned int offset_start , unsigned int size_total )
1129
- {
1130
- unsigned int offset , size ;
1131
- int ret , i ;
1132
- struct xstate_header header ;
1133
-
1134
- /*
1135
- * Currently copy_regset_to_user() starts from pos 0:
1136
- */
1137
- if (unlikely (offset_start != 0 ))
1138
- return - EFAULT ;
1139
-
1140
- /*
1141
- * The destination is a ptrace buffer; we put in only user xstates:
1142
- */
1143
- memset (& header , 0 , sizeof (header ));
1144
- header .xfeatures = xsave -> header .xfeatures ;
1145
- header .xfeatures &= xfeatures_mask_user ();
1146
-
1147
- /*
1148
- * Copy xregs_state->header:
1149
- */
1150
- offset = offsetof(struct xregs_state , header );
1151
- size = sizeof (header );
1152
-
1153
- ret = __copy_xstate_to_user (ubuf , & header , offset , size , size_total );
1154
- if (ret )
1155
- return ret ;
1156
-
1157
- for (i = 0 ; i < XFEATURE_MAX ; i ++ ) {
1158
- /*
1159
- * Copy only in-use xstates:
1160
- */
1161
- if ((header .xfeatures >> i ) & 1 ) {
1162
- void * src = __raw_xsave_addr (xsave , i );
1163
-
1164
- offset = xstate_offsets [i ];
1165
- size = xstate_sizes [i ];
1166
-
1167
- /* The next component has to fit fully into the output buffer: */
1168
- if (offset + size > size_total )
1169
- break ;
1170
-
1171
- ret = __copy_xstate_to_user (ubuf , src , offset , size , size_total );
1172
- if (ret )
1173
- return ret ;
1174
- }
1175
-
1176
- }
1177
-
1178
- if (xfeatures_mxcsr_quirk (header .xfeatures )) {
1179
- offset = offsetof(struct fxregs_state , mxcsr );
1180
- size = MXCSR_AND_FLAGS_SIZE ;
1181
- __copy_xstate_to_user (ubuf , & xsave -> i387 .mxcsr , offset , size , size_total );
1182
- }
1183
-
1184
- /*
1185
- * Fill xsave->i387.sw_reserved value for ptrace frame:
1186
- */
1187
- offset = offsetof(struct fxregs_state , sw_reserved );
1188
- size = sizeof (xstate_fx_sw_bytes );
1189
-
1190
- ret = __copy_xstate_to_user (ubuf , xstate_fx_sw_bytes , offset , size , size_total );
1191
- if (ret )
1192
- return ret ;
1193
-
1194
- return 0 ;
1084
+ fill_gap (& to , & last , size );
1195
1085
}
1196
1086
1197
1087
/*
0 commit comments