aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2010-09-09 18:16:56 -0400
committerTony Luck <tony.luck@intel.com>2010-09-09 18:16:56 -0400
commitf574c843191728d9407b766a027f779dcd27b272 (patch)
tree61f464091fa4d59a2782c2c746ebadc766566fd3 /arch/ia64
parentd56557af19867edb8c0e96f8e26399698a08857f (diff)
[IA64] fix siglock
When ia64 converted to using ticket locks, an inline implementation of trylock/unlock in fsys.S was missed. This was not noticed because in most circumstances it simply resulted in using the slow path because the siglock was apparently not available (under old spinlock rules). Problems occur when the ticket spinlock has value 0x0 (when first initialised, or when it wraps around). At this point the fsys.S code acquires the lock (changing the 0x0 to 0x1. If another process attempts to get the lock at this point, it will change the value from 0x1 to 0x2 (using new ticket lock rules). Then the fsys.S code will free the lock using old spinlock rules by writing 0x0 to it. From here a variety of bad things can happen. Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/kernel/fsys.S46
1 files changed, 39 insertions, 7 deletions
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 3567d54f8cee..471a1e783aca 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -424,14 +424,26 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set
424 andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP 424 andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP
425 425
426#ifdef CONFIG_SMP 426#ifdef CONFIG_SMP
427 mov r17=1 427 // __ticket_spin_trylock(r31)
428 ;; 428 ld4 r17=[r31]
429 cmpxchg4.acq r18=[r31],r17,ar.ccv // try to acquire the lock
430 mov r8=EINVAL // default to EINVAL 429 mov r8=EINVAL // default to EINVAL
431 ;; 430 ;;
431 extr r9=r17,17,15
432 ;;
433 xor r18=r17,r9
434 adds r19=1,r17
435 ;;
436 extr.u r18=r18,0,15
437 ;;
438 cmp.eq p0,p7=0,r18
439(p7) br.cond.spnt.many .lock_contention
440 mov.m ar.ccv=r17
441 ;;
442 cmpxchg4.acq r9=[r31],r19,ar.ccv
443 ;;
444 cmp4.eq p0,p7=r9,r17
445(p7) br.cond.spnt.many .lock_contention
432 ld8 r3=[r2] // re-read current->blocked now that we hold the lock 446 ld8 r3=[r2] // re-read current->blocked now that we hold the lock
433 cmp4.ne p6,p0=r18,r0
434(p6) br.cond.spnt.many .lock_contention
435 ;; 447 ;;
436#else 448#else
437 ld8 r3=[r2] // re-read current->blocked now that we hold the lock 449 ld8 r3=[r2] // re-read current->blocked now that we hold the lock
@@ -490,7 +502,17 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set
490(p6) br.cond.spnt.few 1b // yes -> retry 502(p6) br.cond.spnt.few 1b // yes -> retry
491 503
492#ifdef CONFIG_SMP 504#ifdef CONFIG_SMP
493 st4.rel [r31]=r0 // release the lock 505 // __ticket_spin_unlock(r31)
506 adds r31=2,r31
507 ;;
508 ld2.bias r2=[r31]
509 mov r3=65534
510 ;;
511 adds r2=2,r2
512 ;;
513 and r3=r3,r2
514 ;;
515 st2.rel [r31]=r3
494#endif 516#endif
495 SSM_PSR_I(p0, p9, r31) 517 SSM_PSR_I(p0, p9, r31)
496 ;; 518 ;;
@@ -512,7 +534,17 @@ EX(.fail_efault, (p15) st8 [r34]=r3)
512 534
513.sig_pending: 535.sig_pending:
514#ifdef CONFIG_SMP 536#ifdef CONFIG_SMP
515 st4.rel [r31]=r0 // release the lock 537 // __ticket_spin_unlock(r31)
538 adds r31=2,r31
539 ;;
540 ld2.bias r2=[r31]
541 mov r3=65534
542 ;;
543 adds r2=2,r2
544 ;;
545 and r3=r3,r2
546 ;;
547 st2.rel [r31]=r3
516#endif 548#endif
517 SSM_PSR_I(p0, p9, r17) 549 SSM_PSR_I(p0, p9, r17)
518 ;; 550 ;;