@@ -236,6 +236,28 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
236236
237237#define SWIZ_PTR (p ) ((unsigned char __user *)((p) ^ swiz))
238238
239+ #define __get_user_or_set_dar (_regs , _dest , _addr ) \
240+ ({ \
241+ int rc = 0; \
242+ typeof(_addr) __addr = (_addr); \
243+ if (__get_user_inatomic(_dest, __addr)) { \
244+ _regs->dar = (unsigned long)__addr; \
245+ rc = -EFAULT; \
246+ } \
247+ rc; \
248+ })
249+
250+ #define __put_user_or_set_dar (_regs , _src , _addr ) \
251+ ({ \
252+ int rc = 0; \
253+ typeof(_addr) __addr = (_addr); \
254+ if (__put_user_inatomic(_src, __addr)) { \
255+ _regs->dar = (unsigned long)__addr; \
256+ rc = -EFAULT; \
257+ } \
258+ rc; \
259+ })
260+
239261static int emulate_multiple (struct pt_regs * regs , unsigned char __user * addr ,
240262 unsigned int reg , unsigned int nb ,
241263 unsigned int flags , unsigned int instr ,
@@ -264,9 +286,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
264286 } else {
265287 unsigned long pc = regs -> nip ^ (swiz & 4 );
266288
267- if (__get_user_inatomic ( instr ,
268- (unsigned int __user * )pc ))
289+ if (__get_user_or_set_dar ( regs , instr ,
290+ (unsigned int __user * )pc ))
269291 return - EFAULT ;
292+
270293 if (swiz == 0 && (flags & SW ))
271294 instr = cpu_to_le32 (instr );
272295 nb = (instr >> 11 ) & 0x1f ;
@@ -310,31 +333,31 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
310333 ((nb0 + 3 ) / 4 ) * sizeof (unsigned long ));
311334
312335 for (i = 0 ; i < nb ; ++ i , ++ p )
313- if (__get_user_inatomic ( REG_BYTE (rptr , i ^ bswiz ),
314- SWIZ_PTR (p )))
336+ if (__get_user_or_set_dar ( regs , REG_BYTE (rptr , i ^ bswiz ),
337+ SWIZ_PTR (p )))
315338 return - EFAULT ;
316339 if (nb0 > 0 ) {
317340 rptr = & regs -> gpr [0 ];
318341 addr += nb ;
319342 for (i = 0 ; i < nb0 ; ++ i , ++ p )
320- if (__get_user_inatomic ( REG_BYTE ( rptr ,
321- i ^ bswiz ),
322- SWIZ_PTR (p )))
343+ if (__get_user_or_set_dar ( regs ,
344+ REG_BYTE ( rptr , i ^ bswiz ),
345+ SWIZ_PTR (p )))
323346 return - EFAULT ;
324347 }
325348
326349 } else {
327350 for (i = 0 ; i < nb ; ++ i , ++ p )
328- if (__put_user_inatomic ( REG_BYTE (rptr , i ^ bswiz ),
329- SWIZ_PTR (p )))
351+ if (__put_user_or_set_dar ( regs , REG_BYTE (rptr , i ^ bswiz ),
352+ SWIZ_PTR (p )))
330353 return - EFAULT ;
331354 if (nb0 > 0 ) {
332355 rptr = & regs -> gpr [0 ];
333356 addr += nb ;
334357 for (i = 0 ; i < nb0 ; ++ i , ++ p )
335- if (__put_user_inatomic ( REG_BYTE ( rptr ,
336- i ^ bswiz ),
337- SWIZ_PTR (p )))
358+ if (__put_user_or_set_dar ( regs ,
359+ REG_BYTE ( rptr , i ^ bswiz ),
360+ SWIZ_PTR (p )))
338361 return - EFAULT ;
339362 }
340363 }
@@ -346,29 +369,32 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
346369 * Only POWER6 has these instructions, and it does true little-endian,
347370 * so we don't need the address swizzling.
348371 */
349- static int emulate_fp_pair (unsigned char __user * addr , unsigned int reg ,
350- unsigned int flags )
372+ static int emulate_fp_pair (struct pt_regs * regs , unsigned char __user * addr ,
373+ unsigned int reg , unsigned int flags )
351374{
352375 char * ptr0 = (char * ) & current -> thread .TS_FPR (reg );
353376 char * ptr1 = (char * ) & current -> thread .TS_FPR (reg + 1 );
354- int i , ret , sw = 0 ;
377+ int i , sw = 0 ;
355378
356379 if (reg & 1 )
357380 return 0 ; /* invalid form: FRS/FRT must be even */
358381 if (flags & SW )
359382 sw = 7 ;
360- ret = 0 ;
383+
361384 for (i = 0 ; i < 8 ; ++ i ) {
362385 if (!(flags & ST )) {
363- ret |= __get_user (ptr0 [i ^sw ], addr + i );
364- ret |= __get_user (ptr1 [i ^sw ], addr + i + 8 );
386+ if (__get_user_or_set_dar (regs , ptr0 [i ^sw ], addr + i ))
387+ return - EFAULT ;
388+ if (__get_user_or_set_dar (regs , ptr1 [i ^sw ], addr + i + 8 ))
389+ return - EFAULT ;
365390 } else {
366- ret |= __put_user (ptr0 [i ^sw ], addr + i );
367- ret |= __put_user (ptr1 [i ^sw ], addr + i + 8 );
391+ if (__put_user_or_set_dar (regs , ptr0 [i ^sw ], addr + i ))
392+ return - EFAULT ;
393+ if (__put_user_or_set_dar (regs , ptr1 [i ^sw ], addr + i + 8 ))
394+ return - EFAULT ;
368395 }
369396 }
370- if (ret )
371- return - EFAULT ;
397+
372398 return 1 ; /* exception handled and fixed up */
373399}
374400
@@ -378,24 +404,27 @@ static int emulate_lq_stq(struct pt_regs *regs, unsigned char __user *addr,
378404{
379405 char * ptr0 = (char * )& regs -> gpr [reg ];
380406 char * ptr1 = (char * )& regs -> gpr [reg + 1 ];
381- int i , ret , sw = 0 ;
407+ int i , sw = 0 ;
382408
383409 if (reg & 1 )
384410 return 0 ; /* invalid form: GPR must be even */
385411 if (flags & SW )
386412 sw = 7 ;
387- ret = 0 ;
413+
388414 for (i = 0 ; i < 8 ; ++ i ) {
389415 if (!(flags & ST )) {
390- ret |= __get_user (ptr0 [i ^sw ], addr + i );
391- ret |= __get_user (ptr1 [i ^sw ], addr + i + 8 );
416+ if (__get_user_or_set_dar (regs , ptr0 [i ^sw ], addr + i ))
417+ return - EFAULT ;
418+ if (__get_user_or_set_dar (regs , ptr1 [i ^sw ], addr + i + 8 ))
419+ return - EFAULT ;
392420 } else {
393- ret |= __put_user (ptr0 [i ^sw ], addr + i );
394- ret |= __put_user (ptr1 [i ^sw ], addr + i + 8 );
421+ if (__put_user_or_set_dar (regs , ptr0 [i ^sw ], addr + i ))
422+ return - EFAULT ;
423+ if (__put_user_or_set_dar (regs , ptr1 [i ^sw ], addr + i + 8 ))
424+ return - EFAULT ;
395425 }
396426 }
397- if (ret )
398- return - EFAULT ;
427+
399428 return 1 ; /* exception handled and fixed up */
400429}
401430#endif /* CONFIG_PPC64 */
@@ -688,9 +717,14 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
688717 for (j = 0 ; j < length ; j += elsize ) {
689718 for (i = 0 ; i < elsize ; ++ i ) {
690719 if (flags & ST )
691- ret |= __put_user (ptr [i ^sw ], addr + i );
720+ ret = __put_user_or_set_dar (regs , ptr [i ^sw ],
721+ addr + i );
692722 else
693- ret |= __get_user (ptr [i ^sw ], addr + i );
723+ ret = __get_user_or_set_dar (regs , ptr [i ^sw ],
724+ addr + i );
725+
726+ if (ret )
727+ return ret ;
694728 }
695729 ptr += elsize ;
696730#ifdef __LITTLE_ENDIAN__
@@ -740,7 +774,7 @@ int fix_alignment(struct pt_regs *regs)
740774 unsigned int dsisr ;
741775 unsigned char __user * addr ;
742776 unsigned long p , swiz ;
743- int ret , i ;
777+ int i ;
744778 union data {
745779 u64 ll ;
746780 double dd ;
@@ -923,7 +957,7 @@ int fix_alignment(struct pt_regs *regs)
923957 if (flags & F ) {
924958 /* Special case for 16-byte FP loads and stores */
925959 PPC_WARN_ALIGNMENT (fp_pair , regs );
926- return emulate_fp_pair (addr , reg , flags );
960+ return emulate_fp_pair (regs , addr , reg , flags );
927961 } else {
928962#ifdef CONFIG_PPC64
929963 /* Special case for 16-byte loads and stores */
@@ -953,15 +987,12 @@ int fix_alignment(struct pt_regs *regs)
953987 }
954988
955989 data .ll = 0 ;
956- ret = 0 ;
957990 p = (unsigned long )addr ;
958991
959992 for (i = 0 ; i < nb ; i ++ )
960- ret |= __get_user_inatomic (data .v [start + i ],
961- SWIZ_PTR (p ++ ));
962-
963- if (unlikely (ret ))
964- return - EFAULT ;
993+ if (__get_user_or_set_dar (regs , data .v [start + i ],
994+ SWIZ_PTR (p ++ )))
995+ return - EFAULT ;
965996
966997 } else if (flags & F ) {
967998 data .ll = current -> thread .TS_FPR (reg );
@@ -1031,15 +1062,13 @@ int fix_alignment(struct pt_regs *regs)
10311062 break ;
10321063 }
10331064
1034- ret = 0 ;
10351065 p = (unsigned long )addr ;
10361066
10371067 for (i = 0 ; i < nb ; i ++ )
1038- ret |= __put_user_inatomic (data .v [start + i ],
1039- SWIZ_PTR (p ++ ));
1068+ if (__put_user_or_set_dar (regs , data .v [start + i ],
1069+ SWIZ_PTR (p ++ )))
1070+ return - EFAULT ;
10401071
1041- if (unlikely (ret ))
1042- return - EFAULT ;
10431072 } else if (flags & F )
10441073 current -> thread .TS_FPR (reg ) = data .ll ;
10451074 else
0 commit comments