[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 2/5] xen/ppc: Implement bitops.h
On 01.09.2023 20:25, Shawn Anastasio wrote: > Implement bitops.h, based on Linux's implementation as of commit > 5321d1b1afb9a17302c6cec79f0cbf823eb0d3fc. Though it is based off of > Linux's implementation, this code diverges significantly in a number of > ways: > - Bitmap entries changed to 32-bit words to match X86 and Arm on Xen > - PPC32-specific code paths dropped > - Formatting completely re-done to more closely line up with Xen. > Including 4 space indentation. Isn't ... > Signed-off-by: Shawn Anastasio <sanastasio@xxxxxxxxxxxxxxxxxxxxx> > --- > v3: > - Fix style of inline asm blocks. > - Fix underscore-prefixed macro parameters/variables > - Use __builtin_popcount for hweight* implementation ... this also a divergence worth calling out? > --- a/xen/arch/ppc/include/asm/bitops.h > +++ b/xen/arch/ppc/include/asm/bitops.h > @@ -1,9 +1,333 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Adapted from Linux's arch/powerpc/include/asm/bitops.h. > + * > + * Merged version by David Gibson <david@xxxxxxxxxxxxxxxxxxxxx>. > + * Based on ppc64 versions by: Dave Engebretsen, Todd Inglett, Don > + * Reed, Pat McCarthy, Peter Bergner, Anton Blanchard. They > + * originally took it from the ppc32 code. > + */ > #ifndef _ASM_PPC_BITOPS_H > #define _ASM_PPC_BITOPS_H > > +#include <asm/memory.h> > + > +#define __set_bit(n, p) set_bit(n, p) > +#define __clear_bit(n, p) clear_bit(n, p) > + > +#define BITOP_BITS_PER_WORD 32 > +#define BITOP_MASK(nr) (1UL << ((nr) % BITOP_BITS_PER_WORD)) With the switch to 32-bit operations, doesn't this want to be 1U? > +#define BITOP_WORD(nr) ((nr) / BITOP_BITS_PER_WORD) > +#define BITS_PER_BYTE 8 > + > /* PPC bit number conversion */ > -#define PPC_BITLSHIFT(be) (BITS_PER_LONG - 1 - (be)) > -#define PPC_BIT(bit) (1UL << PPC_BITLSHIFT(bit)) > -#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs)) > +#define PPC_BITLSHIFT(be) (BITS_PER_LONG - 1 - (be)) > +#define PPC_BIT(bit) (1UL << PPC_BITLSHIFT(bit)) > +#define PPC_BITMASK(bs, be) ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs)) > + > +/* Macro for generating the ***_bits() functions */ > +#define DEFINE_BITOP(fn, op, prefix) > \ > +static inline void fn(unsigned long mask, > \ > + volatile unsigned int *p_) > \ > +{ > \ > + unsigned long old; > \ > + unsigned int *p = (unsigned int *)p_; > \ > + asm volatile ( prefix > \ > + "1: lwarx %0,0,%3,0\n" > \ > + #op "%I2 %0,%0,%2\n" > \ > + "stwcx. %0,0,%3\n" > \ > + "bne- 1b\n" > \ > + : "=&r" (old), "+m" (*p) > \ > + : "rK" (mask), "r" (p) > \ > + : "cc", "memory" ); > \ > +} > + > +DEFINE_BITOP(set_bits, or, "") > +DEFINE_BITOP(change_bits, xor, "") > + > +#define DEFINE_CLROP(fn, prefix) > \ > +static inline void fn(unsigned long mask, volatile unsigned int *_p) > \ Leftover leading underscore. > +{ > \ > + unsigned long old; > \ > + unsigned int *p = (unsigned int *)_p; > \ > + asm volatile ( prefix > \ > + "1: lwarx %0,0,%3,0\n" > \ > + "andc %0,%0,%2\n" > \ > + "stwcx. %0,0,%3\n" > \ > + "bne- 1b\n" > \ > + : "=&r" (old), "+m" (*p) > \ > + : "r" (mask), "r" (p) > \ > + : "cc", "memory" ); > \ > +} > + > +DEFINE_CLROP(clear_bits, "") > + > +static inline void set_bit(int nr, volatile void *addr) > +{ > + set_bits(BITOP_MASK(nr), (volatile unsigned int *)addr + BITOP_WORD(nr)); > +} > +static inline void clear_bit(int nr, volatile void *addr) > +{ > + clear_bits(BITOP_MASK(nr), (volatile unsigned int *)addr + > BITOP_WORD(nr)); > +} > + > +/** > + * test_bit - Determine whether a bit is set > + * @nr: bit number to test > + * @addr: Address to start counting from > + */ > +static inline int test_bit(int nr, const volatile void *addr) > +{ > + const volatile unsigned long *p = (const volatile unsigned long *)addr; > + return 1 & (p[BITOP_WORD(nr)] >> (nr & (BITOP_BITS_PER_WORD - 1))); > +} > + > +static inline unsigned long test_and_clear_bits(unsigned long mask, volatile > void *_p) Again. And there are more. Yet here (and below) ... > +{ > + unsigned long old, t; > + unsigned int *p = (unsigned int *)_p; > + > + asm volatile ( PPC_ATOMIC_ENTRY_BARRIER > + "1: lwarx %0,0,%3,0\n" > + "andc %1,%0,%2\n" > + "stwcx. %1,0,%3\n" > + "bne- 1b\n" > + PPC_ATOMIC_EXIT_BARRIER > + : "=&r" (old), "=&r" (t) > + : "r" (mask), "r" (p) > + : "cc", "memory" ); ... do you actually need the helper variable, when there's no "+m" constraint operand? > + return (old & mask); > +} > + > +static inline int test_and_clear_bit(unsigned int nr, > + volatile void *addr) > +{ > + return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0; > +} > + > +#define DEFINE_TESTOP(fn, op, eh) > \ > +static inline unsigned long fn(unsigned long mask, volatile unsigned int > *_p) \ > +{ > \ > + unsigned long old, t; > \ > + unsigned int *p = (unsigned int *)_p; > \ > + asm volatile ( PPC_ATOMIC_ENTRY_BARRIER > \ > + "1: lwarx %0,0,%3,%4\n" > \ > + #op "%I2 %1,%0,%2\n" > \ > + "stwcx. %1,0,%3\n" > \ > + "bne- 1b\n" > \ > + PPC_ATOMIC_EXIT_BARRIER > \ > + : "=&r" (old), "=&r" (t) > \ > + : "rK" (mask), "r" (p), "n" (eh) > \ > + : "cc", "memory" ); > \ > + return (old & mask); > \ > +} > + > +DEFINE_TESTOP(test_and_set_bits, or, 0) Why can't test_and_clear_bits() not use this macro-ization? And if it can't and hence there's only this single use, wouldn't it make sense to avoid going through a macro here, too? > +static inline int test_and_set_bit(unsigned long nr, volatile void *addr) > +{ > + return test_and_set_bits(BITOP_MASK(nr), (volatile unsigned int *)addr + > + BITOP_WORD(nr)) != 0; This wants wrapping differently, e.g. static inline int test_and_set_bit(unsigned long nr, volatile void *addr) { return test_and_set_bits(BITOP_MASK(nr), (volatile unsigned int *)addr + BITOP_WORD(nr)) != 0; } or static inline int test_and_set_bit(unsigned long nr, volatile void *addr) { return test_and_set_bits( BITOP_MASK(nr), (volatile unsigned int *)addr + BITOP_WORD(nr)) != 0; } > +#define flsl(x) generic_flsl(x) > +#define fls(x) generic_fls(x) > +#define ffs(x) ({ unsigned int t_ = (x); fls(t_ & - t_); }) > +#define ffsl(x) ({ unsigned long t_ = (x); flsl(t_ & - t_); }) Nit: No blanks after unary operators, please. > +/* Based on linux/include/asm-generic/bitops/ffz.h */ > +/* > + * ffz - find first zero in word. > + * @word: The word to search > + * > + * Undefined if no zero exists, so code should check against ~0UL first. > + */ > +#define ffz(x) __ffs(~(x)) Nit: Stray double padding blank? Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |