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