git: c9c6985b8a18 - stable/13 - powerpc/atomic: Fix atomic_testand_*_long on powerpc64

From: Navdeep Parhar <np_at_FreeBSD.org>
Date: Wed, 02 Mar 2022 22:08:56 UTC
The branch stable/13 has been updated by np:

URL: https://cgit.FreeBSD.org/src/commit/?id=c9c6985b8a180b2270db83d3a2389d452362dd8f

commit c9c6985b8a180b2270db83d3a2389d452362dd8f
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2022-02-03 23:20:36 +0000
Commit:     Navdeep Parhar <np@FreeBSD.org>
CommitDate: 2022-03-02 22:08:33 +0000

    powerpc/atomic: Fix atomic_testand_*_long on powerpc64
    
    After b5d227b0 FreeBSD was panicking on boot with "Duplicate free" in
    UMA.  Analyzing the asm, the '1' mask was treated as an integer, rather
    than a long, causing 'slw' (shift left word) to be used for the shifting
    instruction, not 'sld' (shift left double).  This means the upper bits
    of the bitfield were not getting used, resulting in corruption of the
    bitfield.
    
    While fixing this, the 'and' check of the mask does not need to be
    recorded, so don't record (drop the '.').
    
    (cherry picked from commit aa4736459ee2d314dc90ae9cbb4ad9c1cf48d796)
---
 sys/powerpc/include/atomic.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h
index c3d353cba3d3..da80cf85fc9f 100644
--- a/sys/powerpc/include/atomic.h
+++ b/sys/powerpc/include/atomic.h
@@ -997,13 +997,13 @@ atomic_swap_64(volatile u_long *p, u_long v)
 static __inline int
 atomic_testandset_int(volatile u_int *p, u_int v)
 {
-	u_int m = (1 << (v & 0x1f));
+	u_int m = (1u << (v & 0x1f));
 	u_int res;
 	u_int tmp;
 
 	__asm __volatile(
 	"1:	lwarx	%0,0,%3\n"
-	"	and.	%1,%0,%4\n"
+	"	and	%1,%0,%4\n"
 	"	or	%0,%0,%4\n"
 	"	stwcx.	%0,0,%3\n"
 	"	bne-	1b\n"
@@ -1017,13 +1017,13 @@ atomic_testandset_int(volatile u_int *p, u_int v)
 static __inline int
 atomic_testandclear_int(volatile u_int *p, u_int v)
 {
-	u_int m = (1 << (v & 0x1f));
+	u_int m = (1u << (v & 0x1f));
 	u_int res;
 	u_int tmp;
 
 	__asm __volatile(
 	"1:	lwarx	%0,0,%3\n"
-	"	and.	%1,%0,%4\n"
+	"	and	%1,%0,%4\n"
 	"	andc	%0,%0,%4\n"
 	"	stwcx.	%0,0,%3\n"
 	"	bne-	1b\n"
@@ -1038,13 +1038,13 @@ atomic_testandclear_int(volatile u_int *p, u_int v)
 static __inline int
 atomic_testandset_long(volatile u_long *p, u_int v)
 {
-	u_long m = (1 << (v & 0x3f));
+	u_long m = (1ul << (v & 0x3f));
 	u_long res;
 	u_long tmp;
 
 	__asm __volatile(
 	"1:	ldarx	%0,0,%3\n"
-	"	and.	%1,%0,%4\n"
+	"	and	%1,%0,%4\n"
 	"	or	%0,%0,%4\n"
 	"	stdcx.	%0,0,%3\n"
 	"	bne-	1b\n"
@@ -1058,13 +1058,13 @@ atomic_testandset_long(volatile u_long *p, u_int v)
 static __inline int
 atomic_testandclear_long(volatile u_long *p, u_int v)
 {
-	u_long m = (1 << (v & 0x3f));
+	u_long m = (1ul << (v & 0x3f));
 	u_long res;
 	u_long tmp;
 
 	__asm __volatile(
 	"1:	ldarx	%0,0,%3\n"
-	"	and.	%1,%0,%4\n"
+	"	and	%1,%0,%4\n"
 	"	andc	%0,%0,%4\n"
 	"	stdcx.	%0,0,%3\n"
 	"	bne-	1b\n"