arch/powerpc/include/asm/bitops.h

Source file repositories/reference/linux-study-clean/arch/powerpc/include/asm/bitops.h

File Facts

System
Linux kernel
Corpus path
arch/powerpc/include/asm/bitops.h
Extension
.h
Size
9394 bytes
Lines
336
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

__builtin_constant_p(mask) && is_rlwinm_mask_valid(~mask)) {\
		asm volatile (						\
			prefix						\
		"1:"	"lwarx	%0,0,%3\n"				\
			"rlwinm	%0,%0,0,%2\n"				\
			"stwcx.	%0,0,%3\n"				\
			"bne- 1b\n"					\
			: "=&r" (old), "+m" (*p)			\
			: "n" (~mask), "r" (p)				\
			: "cc", "memory");				\
	} else {							\
		asm volatile (						\
			prefix						\
		"1:"	PPC_LLARX "%0,0,%3,0\n"				\
			"andc %0,%0,%2\n"				\
			PPC_STLCX "%0,0,%3\n"				\
			"bne- 1b\n"					\
			: "=&r" (old), "+m" (*p)			\
			: "r" (mask), "r" (p)				\
			: "cc", "memory");				\
	}								\
}

DEFINE_CLROP(clear_bits, "")
DEFINE_CLROP(clear_bits_unlock, PPC_RELEASE_BARRIER)

static inline void arch_set_bit(int nr, volatile unsigned long *addr)
{
	set_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
}

static inline void arch_clear_bit(int nr, volatile unsigned long *addr)
{
	clear_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
}

static inline void arch_clear_bit_unlock(int nr, volatile unsigned long *addr)
{
	clear_bits_unlock(BIT_MASK(nr), addr + BIT_WORD(nr));
}

static inline void arch_change_bit(int nr, volatile unsigned long *addr)
{
	change_bits(BIT_MASK(nr), addr + BIT_WORD(nr));
}

/* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output
 * operands. */
#define DEFINE_TESTOP(fn, op, prefix, postfix, eh)	\
static inline unsigned long fn(			\
		unsigned long mask,			\
		volatile unsigned long *_p)		\
{							\
	unsigned long old, t;				\
	unsigned long *p = (unsigned long *)_p;		\
	__asm__ __volatile__ (				\
	prefix						\
"1:"	PPC_LLARX "%0,0,%3,%4\n"			\
	#op "%I2 %1,%0,%2\n"				\
	PPC_STLCX "%1,0,%3\n"				\
	"bne- 1b\n"					\
	postfix						\
	: "=&r" (old), "=&r" (t)			\
	: "rK" (mask), "r" (p), "n" (eh)		\
	: "cc", "memory");				\
	return (old & mask);				\
}

DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
	      PPC_ATOMIC_EXIT_BARRIER, 0)
DEFINE_TESTOP(test_and_set_bits_lock, or, "",
	      PPC_ACQUIRE_BARRIER, IS_ENABLED(CONFIG_PPC64))
DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
	      PPC_ATOMIC_EXIT_BARRIER, 0)

static inline unsigned long test_and_clear_bits(unsigned long mask, volatile unsigned long *_p)
{
	unsigned long old, t;
	unsigned long *p = (unsigned long *)_p;

	if (IS_ENABLED(CONFIG_PPC32) &&
	    __builtin_constant_p(mask) && is_rlwinm_mask_valid(~mask)) {
		asm volatile (
			PPC_ATOMIC_ENTRY_BARRIER
		"1:"	"lwarx %0,0,%3\n"
			"rlwinm	%1,%0,0,%2\n"
			"stwcx. %1,0,%3\n"
			"bne- 1b\n"
			PPC_ATOMIC_EXIT_BARRIER
			: "=&r" (old), "=&r" (t)

Annotation

Implementation Notes