Map PTEs for MAP_SHARED | MAP_LOCKED files on fork
[akaros.git] / kern / arch / x86 / bitops.h
index 33a00bf..86b12ac 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef _ASM_X86_BITOPS_H
-#define _ASM_X86_BITOPS_H
+#pragma once
 
 /*
  * Copyright 1992, Linus Torvalds.
 
 /*
  * Copyright 1992, Linus Torvalds.
@@ -8,15 +7,9 @@
  * __always_inline to avoid problems with older gcc's inlining heuristics.
  */
 
  * __always_inline to avoid problems with older gcc's inlining heuristics.
  */
 
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>
-#include <asm/alternative.h>
-
 #define BIT_64(n)                      (U64_C(1) << (n))
 #define BIT_64(n)                      (U64_C(1) << (n))
-
+#define DECLARE_BITMAP(name,bits) \
+       unsigned long name[(bits+sizeof(unsigned long)*8 - 1)/(sizeof(unsigned long)*8)/*BITS_TO_LONGS(bits)*/]
 /*
  * These have to be done with inline assembly: that way the bit-setting
  * is guaranteed to be atomic. All bit operations return 0 if the bit
 /*
  * These have to be done with inline assembly: that way the bit-setting
  * is guaranteed to be atomic. All bit operations return 0 if the bit
  */
 
 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
  */
 
 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
-/* Technically wrong, but this avoids compilation errors on some gcc
-   versions. */
-#define BITOP_ADDR(x) "=m" (*(volatile long *) (x))
+#error "Get a gcc newer than 4.4.0"
 #else
 #define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
 #endif
 
 #define ADDR                           BITOP_ADDR(addr)
 
 #else
 #define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
 #endif
 
 #define ADDR                           BITOP_ADDR(addr)
 
+#define LOCK_PREFIX "lock "
 /*
  * We do the locked ops that don't return the old value as
  * a mask operation on a byte.
 /*
  * We do the locked ops that don't return the old value as
  * a mask operation on a byte.
@@ -62,12 +54,13 @@ static __always_inline void
 set_bit(unsigned int nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
 set_bit(unsigned int nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
-               asm volatile (LOCK_PREFIX "orb %1,%0":CONST_MASK_ADDR(nr, addr)
-                                         :"iq"((u8) CONST_MASK(nr))
-                                         :"memory");
+               asm volatile(LOCK_PREFIX "orb %1,%0"
+                       : CONST_MASK_ADDR(nr, addr)
+                       : "iq" ((uint8_t)CONST_MASK(nr))
+                       : "memory");
        } else {
        } else {
-               asm volatile (LOCK_PREFIX
-                                         "bts %1,%0":BITOP_ADDR(addr):"Ir"(nr):"memory");
+               asm volatile(LOCK_PREFIX "bts %1,%0"
+                       : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
        }
 }
 
        }
 }
 
@@ -82,7 +75,7 @@ set_bit(unsigned int nr, volatile unsigned long *addr)
  */
 static inline void __set_bit(int nr, volatile unsigned long *addr)
 {
  */
 static inline void __set_bit(int nr, volatile unsigned long *addr)
 {
-       asm volatile ("bts %1,%0":ADDR:"Ir"(nr):"memory");
+       asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
 }
 
 /**
 }
 
 /**
@@ -94,15 +87,25 @@ static inline void __set_bit(int nr, volatile unsigned long *addr)
  * not contain a memory barrier, so if it is used for locking purposes,
  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  * in order to ensure changes are visible on other processors.
  * not contain a memory barrier, so if it is used for locking purposes,
  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  * in order to ensure changes are visible on other processors.
- */
-static __always_inline void clear_bit(int nr, volatile unsigned long *addr)
+ * 
+ * Note from brho: I think the use of LOCK_PREFIX (assuming it is "lock")
+ * provides a memory barrier against hardware reordering accesses around the
+ * LOCK ("lock" serializes).  This lacks a cmb() (called a barrier() in Linux),
+ * which would prevent the compiler from reordering the instructions.  The
+ * above-mentioned smp_mb__before_clear_bit appears to be this cmb(), so it's
+ * not clear what the usage of "memory barrier" means exactly here and
+ * elsewhere in this file. */
+static __always_inline void
+clear_bit(int nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
 {
        if (IS_IMMEDIATE(nr)) {
-               asm volatile (LOCK_PREFIX "andb %1,%0":CONST_MASK_ADDR(nr, addr)
-                                         :"iq"((u8) ~ CONST_MASK(nr)));
+               asm volatile(LOCK_PREFIX "andb %1,%0"
+                       : CONST_MASK_ADDR(nr, addr)
+                       : "iq" ((uint8_t)~CONST_MASK(nr)));
        } else {
        } else {
-               asm volatile (LOCK_PREFIX "btr %1,%0":BITOP_ADDR(addr)
-                                         :"Ir"(nr));
+               asm volatile(LOCK_PREFIX "btr %1,%0"
+                       : BITOP_ADDR(addr)
+                       : "Ir" (nr));
        }
 }
 
        }
 }
 
@@ -116,13 +119,13 @@ static __always_inline void clear_bit(int nr, volatile unsigned long *addr)
  */
 static inline void clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
 {
  */
 static inline void clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
 {
-       barrier();
+       cmb();
        clear_bit(nr, addr);
 }
 
 static inline void __clear_bit(int nr, volatile unsigned long *addr)
 {
        clear_bit(nr, addr);
 }
 
 static inline void __clear_bit(int nr, volatile unsigned long *addr)
 {
-       asm volatile ("btr %1,%0":ADDR:"Ir"(nr));
+       asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
 }
 
 /*
 }
 
 /*
@@ -139,12 +142,12 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr)
  */
 static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
 {
  */
 static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
 {
-       barrier();
+       cmb();
        __clear_bit(nr, addr);
 }
 
        __clear_bit(nr, addr);
 }
 
-#define smp_mb__before_clear_bit()     barrier()
-#define smp_mb__after_clear_bit()      barrier()
+#define smp_mb__before_clear_bit()     cmb()
+#define smp_mb__after_clear_bit()      cmb()
 
 /**
  * __change_bit - Toggle a bit in memory
 
 /**
  * __change_bit - Toggle a bit in memory
@@ -157,7 +160,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr)
  */
 static inline void __change_bit(int nr, volatile unsigned long *addr)
 {
  */
 static inline void __change_bit(int nr, volatile unsigned long *addr)
 {
-       asm volatile ("btc %1,%0":ADDR:"Ir"(nr));
+       asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
 }
 
 /**
 }
 
 /**
@@ -172,11 +175,13 @@ static inline void __change_bit(int nr, volatile unsigned long *addr)
 static inline void change_bit(int nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
 static inline void change_bit(int nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
-               asm volatile (LOCK_PREFIX "xorb %1,%0":CONST_MASK_ADDR(nr, addr)
-                                         :"iq"((u8) CONST_MASK(nr)));
+               asm volatile(LOCK_PREFIX "xorb %1,%0"
+                       : CONST_MASK_ADDR(nr, addr)
+                       : "iq" ((uint8_t)CONST_MASK(nr)));
        } else {
        } else {
-               asm volatile (LOCK_PREFIX "btc %1,%0":BITOP_ADDR(addr)
-                                         :"Ir"(nr));
+               asm volatile(LOCK_PREFIX "btc %1,%0"
+                       : BITOP_ADDR(addr)
+                       : "Ir" (nr));
        }
 }
 
        }
 }
 
@@ -192,8 +197,8 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-       asm volatile (LOCK_PREFIX "bts %2,%1\n\t"
-                                 "sbb %0,%0":"=r"(oldbit), ADDR:"Ir"(nr):"memory");
+       asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
+                    "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
 
        return oldbit;
 }
 
        return oldbit;
 }
@@ -224,7 +229,10 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-asm("bts %2,%1\n\t" "sbb %0,%0": "=r"(oldbit), ADDR:"Ir"(nr));
+       asm("bts %2,%1\n\t"
+           "sbb %0,%0"
+           : "=r" (oldbit), ADDR
+           : "Ir" (nr));
        return oldbit;
 }
 
        return oldbit;
 }
 
@@ -240,8 +248,9 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-       asm volatile (LOCK_PREFIX "btr %2,%1\n\t"
-                                 "sbb %0,%0":"=r"(oldbit), ADDR:"Ir"(nr):"memory");
+       asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
 
        return oldbit;
 }
 
        return oldbit;
 }
@@ -266,7 +275,10 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-       asm volatile ("btr %2,%1\n\t" "sbb %0,%0":"=r" (oldbit), ADDR:"Ir"(nr));
+       asm volatile("btr %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit), ADDR
+                    : "Ir" (nr));
        return oldbit;
 }
 
        return oldbit;
 }
 
@@ -275,8 +287,10 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-       asm volatile ("btc %2,%1\n\t"
-                                 "sbb %0,%0":"=r" (oldbit), ADDR:"Ir"(nr):"memory");
+       asm volatile("btc %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit), ADDR
+                    : "Ir" (nr) : "memory");
 
        return oldbit;
 }
 
        return oldbit;
 }
@@ -293,42 +307,35 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
 {
        int oldbit;
 
 {
        int oldbit;
 
-       asm volatile (LOCK_PREFIX "btc %2,%1\n\t"
-                                 "sbb %0,%0":"=r"(oldbit), ADDR:"Ir"(nr):"memory");
+       asm volatile(LOCK_PREFIX "btc %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
 
        return oldbit;
 }
 
 
        return oldbit;
 }
 
-static __always_inline int constant_test_bit(unsigned int nr,
-                                                                                        const volatile unsigned long *addr)
+static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
 {
 {
-       return ((1UL << (nr % BITS_PER_LONG)) & (addr[nr / BITS_PER_LONG])) != 0;
+       return ((1UL << (nr % BITS_PER_LONG)) &
+               (addr[nr / BITS_PER_LONG])) != 0;
 }
 
 static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
 {
        int oldbit;
 
 }
 
 static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
 {
        int oldbit;
 
-       asm volatile ("bt %2,%1\n\t" "sbb %0,%0":"=r" (oldbit)
-                                 :"m"(*(unsigned long *)addr), "Ir"(nr));
+       asm volatile("bt %2,%1\n\t"
+                    "sbb %0,%0"
+                    : "=r" (oldbit)
+                    : "m" (*(unsigned long *)addr), "Ir" (nr));
 
        return oldbit;
 }
 
 
        return oldbit;
 }
 
-#if 0  /* Fool kernel-doc since it doesn't do macros yet */
-/**
- * test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static int test_bit(int nr, const volatile unsigned long *addr);
-#endif
-
-#define test_bit(nr, addr)                     \
-       (__builtin_constant_p((nr))             \
-        ? constant_test_bit((nr), (addr))      \
-        : variable_test_bit((nr), (addr)))
-
+#define test_bit(nr, addr)                      \
+        (__builtin_constant_p((nr))             \
+         ? constant_test_bit((nr), (addr))      \
+         : variable_test_bit((nr), (addr)))
 /**
  * __ffs - find first set bit in word
  * @word: The word to search
 /**
  * __ffs - find first set bit in word
  * @word: The word to search
@@ -337,8 +344,9 @@ static int test_bit(int nr, const volatile unsigned long *addr);
  */
 static inline unsigned long __ffs(unsigned long word)
 {
  */
 static inline unsigned long __ffs(unsigned long word)
 {
-asm("rep; bsf %1,%0":"=r"(word)
-:              "rm"(word));
+       asm("rep; bsf %1,%0"
+               : "=r" (word)
+               : "rm" (word));
        return word;
 }
 
        return word;
 }
 
@@ -350,8 +358,9 @@ asm("rep; bsf %1,%0":"=r"(word)
  */
 static inline unsigned long ffz(unsigned long word)
 {
  */
 static inline unsigned long ffz(unsigned long word)
 {
-asm("rep; bsf %1,%0":"=r"(word)
-:              "r"(~word));
+       asm("rep; bsf %1,%0"
+               : "=r" (word)
+               : "r" (~word));
        return word;
 }
 
        return word;
 }
 
@@ -363,14 +372,14 @@ asm("rep; bsf %1,%0":"=r"(word)
  */
 static inline unsigned long __fls(unsigned long word)
 {
  */
 static inline unsigned long __fls(unsigned long word)
 {
-asm("bsr %1,%0":"=r"(word)
-:              "rm"(word));
+       asm("bsr %1,%0"
+           : "=r" (word)
+           : "rm" (word));
        return word;
 }
 
 #undef ADDR
 
        return word;
 }
 
 #undef ADDR
 
-#ifdef __KERNEL__
 /**
  * ffs - find first set bit in word
  * @x: the word to search
 /**
  * ffs - find first set bit in word
  * @x: the word to search
@@ -386,7 +395,6 @@ static inline int ffs(int x)
 {
        int r;
 
 {
        int r;
 
-#ifdef CONFIG_X86_64
        /*
         * AMD64 says BSFL won't clobber the dest reg if x==0; Intel64 says the
         * dest reg is undefined if x==0, but their CPU architect says its
        /*
         * AMD64 says BSFL won't clobber the dest reg if x==0; Intel64 says the
         * dest reg is undefined if x==0, but their CPU architect says its
@@ -396,13 +404,9 @@ static inline int ffs(int x)
         * We cannot do this on 32 bits because at the very least some
         * 486 CPUs did not behave this way.
         */
         * We cannot do this on 32 bits because at the very least some
         * 486 CPUs did not behave this way.
         */
-asm("bsfl %1,%0":"=r"(r)
-:              "rm"(x), "0"(-1));
-#elif defined(CONFIG_X86_CMOV)
-asm("bsfl %1,%0\n\t" "cmovzl %2,%0": "=&r"(r):"rm"(x), "r"(-1));
-#else
-asm("bsfl %1,%0\n\t" "jnz 1f\n\t" "movl $-1,%0\n" "1:": "=r"(r):"rm"(x));
-#endif
+       asm("bsfl %1,%0"
+           : "=r" (r)
+           : "rm" (x), "0" (-1));
        return r + 1;
 }
 
        return r + 1;
 }
 
@@ -421,7 +425,6 @@ static inline int fls(int x)
 {
        int r;
 
 {
        int r;
 
-#ifdef CONFIG_X86_64
        /*
         * AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
         * dest reg is undefined if x==0, but their CPU architect says its
        /*
         * AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
         * dest reg is undefined if x==0, but their CPU architect says its
@@ -431,13 +434,9 @@ static inline int fls(int x)
         * We cannot do this on 32 bits because at the very least some
         * 486 CPUs did not behave this way.
         */
         * We cannot do this on 32 bits because at the very least some
         * 486 CPUs did not behave this way.
         */
-asm("bsrl %1,%0":"=r"(r)
-:              "rm"(x), "0"(-1));
-#elif defined(CONFIG_X86_CMOV)
-asm("bsrl %1,%0\n\t" "cmovzl %2,%0": "=&r"(r):"rm"(x), "rm"(-1));
-#else
-asm("bsrl %1,%0\n\t" "jnz 1f\n\t" "movl $-1,%0\n" "1:": "=r"(r):"rm"(x));
-#endif
+       asm("bsrl %1,%0"
+           : "=r" (r)
+           : "rm" (x), "0" (-1));
        return r + 1;
 }
 
        return r + 1;
 }
 
@@ -452,8 +451,7 @@ asm("bsrl %1,%0\n\t" "jnz 1f\n\t" "movl $-1,%0\n" "1:": "=r"(r):"rm"(x));
  * set bit if value is nonzero. The last (most significant) bit is
  * at position 64.
  */
  * set bit if value is nonzero. The last (most significant) bit is
  * at position 64.
  */
-#ifdef CONFIG_X86_64
-static __always_inline int fls64(__u64 x)
+static __always_inline int fls64(uint64_t x)
 {
        int bitpos = -1;
        /*
 {
        int bitpos = -1;
        /*
@@ -461,27 +459,8 @@ static __always_inline int fls64(__u64 x)
         * dest reg is undefined if x==0, but their CPU architect says its
         * value is written to set it to the same as before.
         */
         * dest reg is undefined if x==0, but their CPU architect says its
         * value is written to set it to the same as before.
         */
-asm("bsrq %1,%q0":"+r"(bitpos)
-:              "rm"(x));
+       asm("bsrq %1,%q0"
+           : "+r" (bitpos)
+           : "rm" (x));
        return bitpos + 1;
 }
        return bitpos + 1;
 }
-#else
-#include <asm-generic/bitops/fls64.h>
-#endif
-
-#include <asm-generic/bitops/find.h>
-
-#include <asm-generic/bitops/sched.h>
-
-#define ARCH_HAS_FAST_MULTIPLIER 1
-
-#include <asm/arch_hweight.h>
-
-#include <asm-generic/bitops/const_hweight.h>
-
-#include <asm-generic/bitops/le.h>
-
-#include <asm-generic/bitops/ext2-atomic-setbit.h>
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_X86_BITOPS_H */