xref: /kvm-unit-tests/lib/arm/bitops.c (revision c2a95639b4cc7eb7f4f05a92c965e6ce5c39bccb)
1f20e2561SAndrew Jones /*
249f758b8SAndrew Jones  * Adapted from
3f20e2561SAndrew Jones  *   include/asm-generic/bitops/atomic.h
4f20e2561SAndrew Jones  *
549f758b8SAndrew Jones  * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com>
6f20e2561SAndrew Jones  *
749f758b8SAndrew Jones  * This work is licensed under the terms of the GNU GPL, version 2.
8f20e2561SAndrew Jones  */
9*c2a95639SPaolo Bonzini #include "libcflat.h"
106ed97c50SPeter Feiner #include <bitops.h>
11f20e2561SAndrew Jones #include <asm/barrier.h>
12f20e2561SAndrew Jones #include <asm/mmu.h>
13f20e2561SAndrew Jones 
set_bit(int nr,volatile unsigned long * addr)14f20e2561SAndrew Jones void set_bit(int nr, volatile unsigned long *addr)
15f20e2561SAndrew Jones {
16f20e2561SAndrew Jones 	volatile unsigned long *word = addr + BIT_WORD(nr);
17f20e2561SAndrew Jones 	unsigned long mask = BIT_MASK(nr);
18f20e2561SAndrew Jones 
19f20e2561SAndrew Jones 	if (mmu_enabled())
20f20e2561SAndrew Jones 		ATOMIC_BITOP("orr", mask, word);
21f20e2561SAndrew Jones 	else
22f20e2561SAndrew Jones 		*word |= mask;
23f20e2561SAndrew Jones 	smp_mb();
24f20e2561SAndrew Jones }
25f20e2561SAndrew Jones 
clear_bit(int nr,volatile unsigned long * addr)26f20e2561SAndrew Jones void clear_bit(int nr, volatile unsigned long *addr)
27f20e2561SAndrew Jones {
28f20e2561SAndrew Jones 	volatile unsigned long *word = addr + BIT_WORD(nr);
29f20e2561SAndrew Jones 	unsigned long mask = BIT_MASK(nr);
30f20e2561SAndrew Jones 
31f20e2561SAndrew Jones 	if (mmu_enabled())
32f20e2561SAndrew Jones 		ATOMIC_BITOP("bic", mask, word);
33f20e2561SAndrew Jones 	else
34f20e2561SAndrew Jones 		*word &= ~mask;
35f20e2561SAndrew Jones 	smp_mb();
36f20e2561SAndrew Jones }
37f20e2561SAndrew Jones 
test_bit(int nr,const volatile unsigned long * addr)38f20e2561SAndrew Jones int test_bit(int nr, const volatile unsigned long *addr)
39f20e2561SAndrew Jones {
40f20e2561SAndrew Jones 	const volatile unsigned long *word = addr + BIT_WORD(nr);
41f20e2561SAndrew Jones 	unsigned long mask = BIT_MASK(nr);
42f20e2561SAndrew Jones 
43f20e2561SAndrew Jones 	return (*word & mask) != 0;
44f20e2561SAndrew Jones }
45f20e2561SAndrew Jones 
test_and_set_bit(int nr,volatile unsigned long * addr)46f20e2561SAndrew Jones int test_and_set_bit(int nr, volatile unsigned long *addr)
47f20e2561SAndrew Jones {
48f20e2561SAndrew Jones 	volatile unsigned long *word = addr + BIT_WORD(nr);
49f20e2561SAndrew Jones 	unsigned long mask = BIT_MASK(nr);
50f20e2561SAndrew Jones 	unsigned long old;
51f20e2561SAndrew Jones 
52f20e2561SAndrew Jones 	smp_mb();
53f20e2561SAndrew Jones 
54f20e2561SAndrew Jones 	if (mmu_enabled()) {
55f20e2561SAndrew Jones 		ATOMIC_TESTOP("orr", mask, word, old);
56f20e2561SAndrew Jones 	} else {
57f20e2561SAndrew Jones 		old = *word;
58f20e2561SAndrew Jones 		*word = old | mask;
59f20e2561SAndrew Jones 	}
60f20e2561SAndrew Jones 	smp_mb();
61f20e2561SAndrew Jones 
62f20e2561SAndrew Jones 	return (old & mask) != 0;
63f20e2561SAndrew Jones }
64f20e2561SAndrew Jones 
test_and_clear_bit(int nr,volatile unsigned long * addr)65f20e2561SAndrew Jones int test_and_clear_bit(int nr, volatile unsigned long *addr)
66f20e2561SAndrew Jones {
67f20e2561SAndrew Jones 	volatile unsigned long *word = addr + BIT_WORD(nr);
68f20e2561SAndrew Jones 	unsigned long mask = BIT_MASK(nr);
69f20e2561SAndrew Jones 	unsigned long old;
70f20e2561SAndrew Jones 
71f20e2561SAndrew Jones 	smp_mb();
72f20e2561SAndrew Jones 
73f20e2561SAndrew Jones 	if (mmu_enabled()) {
74f20e2561SAndrew Jones 		ATOMIC_TESTOP("bic", mask, word, old);
75f20e2561SAndrew Jones 	} else {
76f20e2561SAndrew Jones 		old = *word;
77f20e2561SAndrew Jones 		*word = old & ~mask;
78f20e2561SAndrew Jones 	}
79f20e2561SAndrew Jones 	smp_mb();
80f20e2561SAndrew Jones 
81f20e2561SAndrew Jones 	return (old & mask) != 0;
82f20e2561SAndrew Jones }
83