@@ -957,18 +957,31 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
957
957
return true;
958
958
}
959
959
960
- /*
961
- * This is similar to user_regset_copyout(), but will not add offset to
962
- * the source data pointer or increment pos, count, kbuf, and ubuf.
963
- */
964
- static inline void
965
- __copy_xstate_to_kernel (void * kbuf , const void * data ,
966
- unsigned int offset , unsigned int size , unsigned int size_total )
960
+ static void fill_gap (unsigned to , void * * kbuf , unsigned * pos , unsigned * count )
967
961
{
968
- if (offset < size_total ) {
969
- unsigned int copy = min (size , size_total - offset );
962
+ if (* pos < to ) {
963
+ unsigned size = to - * pos ;
964
+
965
+ if (size > * count )
966
+ size = * count ;
967
+ memcpy (* kbuf , (void * )& init_fpstate .xsave + * pos , size );
968
+ * kbuf += size ;
969
+ * pos += size ;
970
+ * count -= size ;
971
+ }
972
+ }
970
973
971
- memcpy (kbuf + offset , data , copy );
974
+ static void copy_part (unsigned offset , unsigned size , void * from ,
975
+ void * * kbuf , unsigned * pos , unsigned * count )
976
+ {
977
+ fill_gap (offset , kbuf , pos , count );
978
+ if (size > * count )
979
+ size = * count ;
980
+ if (size ) {
981
+ memcpy (* kbuf , from , size );
982
+ * kbuf += size ;
983
+ * pos += size ;
984
+ * count -= size ;
972
985
}
973
986
}
974
987
@@ -981,8 +994,9 @@ __copy_xstate_to_kernel(void *kbuf, const void *data,
981
994
*/
982
995
int copy_xstate_to_kernel (void * kbuf , struct xregs_state * xsave , unsigned int offset_start , unsigned int size_total )
983
996
{
984
- unsigned int offset , size ;
985
997
struct xstate_header header ;
998
+ const unsigned off_mxcsr = offsetof(struct fxregs_state , mxcsr );
999
+ unsigned count = size_total ;
986
1000
int i ;
987
1001
988
1002
/*
@@ -998,46 +1012,42 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
998
1012
header .xfeatures = xsave -> header .xfeatures ;
999
1013
header .xfeatures &= ~XFEATURE_MASK_SUPERVISOR ;
1000
1014
1015
+ if (header .xfeatures & XFEATURE_MASK_FP )
1016
+ copy_part (0 , off_mxcsr ,
1017
+ & xsave -> i387 , & kbuf , & offset_start , & count );
1018
+ if (header .xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM ))
1019
+ copy_part (off_mxcsr , MXCSR_AND_FLAGS_SIZE ,
1020
+ & xsave -> i387 .mxcsr , & kbuf , & offset_start , & count );
1021
+ if (header .xfeatures & XFEATURE_MASK_FP )
1022
+ copy_part (offsetof(struct fxregs_state , st_space ), 128 ,
1023
+ & xsave -> i387 .st_space , & kbuf , & offset_start , & count );
1024
+ if (header .xfeatures & XFEATURE_MASK_SSE )
1025
+ copy_part (xstate_offsets [XFEATURE_MASK_SSE ], 256 ,
1026
+ & xsave -> i387 .xmm_space , & kbuf , & offset_start , & count );
1027
+ /*
1028
+ * Fill xsave->i387.sw_reserved value for ptrace frame:
1029
+ */
1030
+ copy_part (offsetof(struct fxregs_state , sw_reserved ), 48 ,
1031
+ xstate_fx_sw_bytes , & kbuf , & offset_start , & count );
1001
1032
/*
1002
1033
* Copy xregs_state->header:
1003
1034
*/
1004
- offset = offsetof(struct xregs_state , header );
1005
- size = sizeof (header );
1006
-
1007
- __copy_xstate_to_kernel (kbuf , & header , offset , size , size_total );
1035
+ copy_part (offsetof(struct xregs_state , header ), sizeof (header ),
1036
+ & header , & kbuf , & offset_start , & count );
1008
1037
1009
- for (i = 0 ; i < XFEATURE_MAX ; i ++ ) {
1038
+ for (i = FIRST_EXTENDED_XFEATURE ; i < XFEATURE_MAX ; i ++ ) {
1010
1039
/*
1011
1040
* Copy only in-use xstates:
1012
1041
*/
1013
1042
if ((header .xfeatures >> i ) & 1 ) {
1014
1043
void * src = __raw_xsave_addr (xsave , i );
1015
1044
1016
- offset = xstate_offsets [i ];
1017
- size = xstate_sizes [i ];
1018
-
1019
- /* The next component has to fit fully into the output buffer: */
1020
- if (offset + size > size_total )
1021
- break ;
1022
-
1023
- __copy_xstate_to_kernel (kbuf , src , offset , size , size_total );
1045
+ copy_part (xstate_offsets [i ], xstate_sizes [i ],
1046
+ src , & kbuf , & offset_start , & count );
1024
1047
}
1025
1048
1026
1049
}
1027
-
1028
- if (xfeatures_mxcsr_quirk (header .xfeatures )) {
1029
- offset = offsetof(struct fxregs_state , mxcsr );
1030
- size = MXCSR_AND_FLAGS_SIZE ;
1031
- __copy_xstate_to_kernel (kbuf , & xsave -> i387 .mxcsr , offset , size , size_total );
1032
- }
1033
-
1034
- /*
1035
- * Fill xsave->i387.sw_reserved value for ptrace frame:
1036
- */
1037
- offset = offsetof(struct fxregs_state , sw_reserved );
1038
- size = sizeof (xstate_fx_sw_bytes );
1039
-
1040
- __copy_xstate_to_kernel (kbuf , xstate_fx_sw_bytes , offset , size , size_total );
1050
+ fill_gap (size_total , & kbuf , & offset_start , & count );
1041
1051
1042
1052
return 0 ;
1043
1053
}
0 commit comments