浏览代码

MIPS: __raw_spin_lock() may spin forever on ticket wrap.

If the lock is not acquired and has to spin *and* the second attempt
to acquire the lock fails, the delay time is not masked by the ticket
range mask.  If the ticket number wraps around to zero, the result is
that the lock sampling delay is essentially infinite (due to casting
-1 to an unsigned int).

The fix: Always mask the difference between my_ticket and the current
ticket value before calculating the delay.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
David Daney 16 年之前
父节点
当前提交
0e6826c73c
共有 1 个文件被更改,包括 4 次插入4 次删除
  1. 4 4
      arch/mips/include/asm/spinlock.h

+ 4 - 4
arch/mips/include/asm/spinlock.h

@@ -76,7 +76,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"2:							\n"
 		"2:							\n"
 		"	.subsection 2					\n"
 		"	.subsection 2					\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
-		"5:	sll	%[ticket], 5				\n"
+		"	sll	%[ticket], 5				\n"
 		"							\n"
 		"							\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"	 subu	%[ticket], 1				\n"
 		"	 subu	%[ticket], 1				\n"
@@ -85,7 +85,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
-		"	b	5b					\n"
+		"	b	4b					\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.previous					\n"
 		"	.set pop					\n"
 		"	.set pop					\n"
@@ -113,7 +113,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"	 ll	%[ticket], %[ticket_ptr]		\n"
 		"	 ll	%[ticket], %[ticket_ptr]		\n"
 		"							\n"
 		"							\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"4:	andi	%[ticket], %[ticket], 0x1fff		\n"
-		"5:	sll	%[ticket], 5				\n"
+		"	sll	%[ticket], 5				\n"
 		"							\n"
 		"							\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"6:	bnez	%[ticket], 6b				\n"
 		"	 subu	%[ticket], 1				\n"
 		"	 subu	%[ticket], 1				\n"
@@ -122,7 +122,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	andi	%[ticket], %[ticket], 0x1fff		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	beq	%[ticket], %[my_ticket], 2b		\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
 		"	 subu	%[ticket], %[my_ticket], %[ticket]	\n"
-		"	b	5b					\n"
+		"	b	4b					\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	 subu	%[ticket], %[ticket], 1			\n"
 		"	.previous					\n"
 		"	.previous					\n"
 		"	.set pop					\n"
 		"	.set pop					\n"