@@ -957,18 +957,31 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
957957 return true;
958958}
959959
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 )
967961{
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+ }
970973
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 ;
972985 }
973986}
974987
@@ -981,8 +994,9 @@ __copy_xstate_to_kernel(void *kbuf, const void *data,
981994 */
982995int copy_xstate_to_kernel (void * kbuf , struct xregs_state * xsave , unsigned int offset_start , unsigned int size_total )
983996{
984- unsigned int offset , size ;
985997 struct xstate_header header ;
998+ const unsigned off_mxcsr = offsetof(struct fxregs_state , mxcsr );
999+ unsigned count = size_total ;
9861000 int i ;
9871001
9881002 /*
@@ -998,46 +1012,42 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of
9981012 header .xfeatures = xsave -> header .xfeatures ;
9991013 header .xfeatures &= ~XFEATURE_MASK_SUPERVISOR ;
10001014
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 );
10011032 /*
10021033 * Copy xregs_state->header:
10031034 */
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 );
10081037
1009- for (i = 0 ; i < XFEATURE_MAX ; i ++ ) {
1038+ for (i = FIRST_EXTENDED_XFEATURE ; i < XFEATURE_MAX ; i ++ ) {
10101039 /*
10111040 * Copy only in-use xstates:
10121041 */
10131042 if ((header .xfeatures >> i ) & 1 ) {
10141043 void * src = __raw_xsave_addr (xsave , i );
10151044
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 );
10241047 }
10251048
10261049 }
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 );
10411051
10421052 return 0 ;
10431053}
0 commit comments