aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/hw/intc/arm_gicv3_common.h54
-rw-r--r--include/qemu/bitmap.h8
-rw-r--r--include/qemu/bitops.h172
3 files changed, 191 insertions, 43 deletions
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index cd09bee3bc..a3d6a0e507 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -51,13 +51,13 @@
/* Maximum number of list registers (architectural limit) */
#define GICV3_LR_MAX 16
-/* For some distributor fields we want to model the array of 32-bit
+/*
+ * For some distributor fields we want to model the array of 32-bit
* register values which hold various bitmaps corresponding to enabled,
- * pending, etc bits. These macros and functions facilitate that; the
- * APIs are generally modelled on the generic bitmap.h functions
- * (which are unsuitable here because they use 'unsigned long' as the
- * underlying storage type, which is very awkward when you need to
- * access the data as 32-bit values.)
+ * pending, etc bits. We use the set_bit32() etc family of functions
+ * from bitops.h for this. For a few cases we need to implement some
+ * extra operations.
+ *
* Each bitmap contains a bit for each interrupt. Although there is
* space for the PPIs and SGIs, those bits (the first 32) are never
* used as that state lives in the redistributor. The unused bits are
@@ -65,39 +65,13 @@
* avoids bugs where we forget to subtract GIC_INTERNAL from an
* interrupt number.
*/
-#define GICV3_BMP_SIZE DIV_ROUND_UP(GICV3_MAXIRQ, 32)
-
-#define GIC_DECLARE_BITMAP(name) \
- uint32_t name[GICV3_BMP_SIZE]
-
-#define GIC_BIT_MASK(nr) (1U << ((nr) % 32))
-#define GIC_BIT_WORD(nr) ((nr) / 32)
-
-static inline void gic_bmp_set_bit(int nr, uint32_t *addr)
-{
- uint32_t mask = GIC_BIT_MASK(nr);
- uint32_t *p = addr + GIC_BIT_WORD(nr);
-
- *p |= mask;
-}
-
-static inline void gic_bmp_clear_bit(int nr, uint32_t *addr)
-{
- uint32_t mask = GIC_BIT_MASK(nr);
- uint32_t *p = addr + GIC_BIT_WORD(nr);
-
- *p &= ~mask;
-}
-
-static inline int gic_bmp_test_bit(int nr, const uint32_t *addr)
-{
- return 1U & (addr[GIC_BIT_WORD(nr)] >> (nr & 31));
-}
+#define GIC_DECLARE_BITMAP(name) DECLARE_BITMAP32(name, GICV3_MAXIRQ)
+#define GICV3_BMP_SIZE BITS_TO_U32S(GICV3_MAXIRQ)
static inline void gic_bmp_replace_bit(int nr, uint32_t *addr, int val)
{
- uint32_t mask = GIC_BIT_MASK(nr);
- uint32_t *p = addr + GIC_BIT_WORD(nr);
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
*p &= ~mask;
*p |= (val & 1U) << (nr % 32);
@@ -106,7 +80,7 @@ static inline void gic_bmp_replace_bit(int nr, uint32_t *addr, int val)
/* Return a pointer to the 32-bit word containing the specified bit. */
static inline uint32_t *gic_bmp_ptr32(uint32_t *addr, int nr)
{
- return addr + GIC_BIT_WORD(nr);
+ return addr + BIT32_WORD(nr);
}
typedef struct GICv3State GICv3State;
@@ -301,15 +275,15 @@ struct GICv3State {
#define GICV3_BITMAP_ACCESSORS(BMP) \
static inline void gicv3_gicd_##BMP##_set(GICv3State *s, int irq) \
{ \
- gic_bmp_set_bit(irq, s->BMP); \
+ set_bit32(irq, s->BMP); \
} \
static inline int gicv3_gicd_##BMP##_test(GICv3State *s, int irq) \
{ \
- return gic_bmp_test_bit(irq, s->BMP); \
+ return test_bit32(irq, s->BMP); \
} \
static inline void gicv3_gicd_##BMP##_clear(GICv3State *s, int irq) \
{ \
- gic_bmp_clear_bit(irq, s->BMP); \
+ clear_bit32(irq, s->BMP); \
} \
static inline void gicv3_gicd_##BMP##_replace(GICv3State *s, \
int irq, int value) \
diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
index 1cf288445f..0044333cb5 100644
--- a/include/qemu/bitmap.h
+++ b/include/qemu/bitmap.h
@@ -69,6 +69,14 @@
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
+/*
+ * This is for use with the bit32 versions of set_bit() etc;
+ * we don't currently support the full range of bitmap operations
+ * on bitmaps backed by an array of uint32_t.
+ */
+#define DECLARE_BITMAP32(name, bits) \
+ uint32_t name[BITS_TO_U32S(bits)]
+
#define small_nbits(nbits) \
((nbits) <= BITS_PER_LONG)
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index 2c0a2fe751..c7b838a628 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -18,17 +18,48 @@
#define BITS_PER_BYTE CHAR_BIT
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#define BITS_TO_U32S(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t))
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
-#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
-#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
-#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#define MAKE_64BIT_MASK(shift, length) \
(((~0ULL) >> (64 - (length))) << (shift))
/**
+ * DOC: Functions operating on arrays of bits
+ *
+ * We provide a set of functions which work on arbitrary-length arrays of
+ * bits. These come in several flavours which vary in what the type of the
+ * underlying storage for the bits is:
+ *
+ * - Bits stored in an array of 'unsigned long': set_bit(), clear_bit(), etc
+ * - Bits stored in an array of 'uint32_t': set_bit32(), clear_bit32(), etc
+ *
+ * Because the 'unsigned long' type has a size which varies between
+ * host systems, the versions using 'uint32_t' are often preferable.
+ * This is particularly the case in a device model where there may
+ * be some guest-visible register view of the bit array.
+ *
+ * We do not currently implement uint32_t versions of find_last_bit(),
+ * find_next_bit(), find_next_zero_bit(), find_first_bit() or
+ * find_first_zero_bit(), because we haven't yet needed them. If you
+ * need them you should implement them similarly to the 'unsigned long'
+ * versions.
+ *
+ * You can declare a bitmap to be used with these functions via the
+ * DECLARE_BITMAP and DECLARE_BITMAP32 macros in bitmap.h.
+ */
+
+/**
+ * DOC: 'unsigned long' bit array APIs
+ */
+
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+
+/**
* set_bit - Set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
@@ -225,6 +256,141 @@ static inline unsigned long find_first_zero_bit(const unsigned long *addr,
}
/**
+ * DOC: 'uint32_t' bit array APIs
+ */
+
+#define BIT32_MASK(nr) (1UL << ((nr) % 32))
+#define BIT32_WORD(nr) ((nr) / 32)
+
+/**
+ * set_bit32 - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+static inline void set_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+
+ *p |= mask;
+}
+
+/**
+ * set_bit32_atomic - Set a bit in memory atomically
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+static inline void set_bit32_atomic(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+
+ qatomic_or(p, mask);
+}
+
+/**
+ * clear_bit32 - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+static inline void clear_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+
+ *p &= ~mask;
+}
+
+/**
+ * clear_bit32_atomic - Clears a bit in memory atomically
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+static inline void clear_bit32_atomic(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+
+ return qatomic_and(p, ~mask);
+}
+
+/**
+ * change_bit32 - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+static inline void change_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+
+ *p ^= mask;
+}
+
+/**
+ * test_and_set_bit32 - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int test_and_set_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+ uint32_t old = *p;
+
+ *p = old | mask;
+ return (old & mask) != 0;
+}
+
+/**
+ * test_and_clear_bit32 - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+static inline int test_and_clear_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+ uint32_t old = *p;
+
+ *p = old & ~mask;
+ return (old & mask) != 0;
+}
+
+/**
+ * test_and_change_bit32 - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+static inline int test_and_change_bit32(long nr, uint32_t *addr)
+{
+ uint32_t mask = BIT32_MASK(nr);
+ uint32_t *p = addr + BIT32_WORD(nr);
+ uint32_t old = *p;
+
+ *p = old ^ mask;
+ return (old & mask) != 0;
+}
+
+/**
+ * test_bit32 - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit32(long nr, const uint32_t *addr)
+{
+ return 1U & (addr[BIT32_WORD(nr)] >> (nr & 31));
+}
+
+/**
+ * DOC: Miscellaneous bit operations on single values
+ *
+ * These functions are a collection of useful operations
+ * (rotations, bit extract, bit deposit, etc) on single
+ * integer values.
+ */
+
+/**
* rol8 - rotate an 8-bit value left
* @word: value to rotate
* @shift: bits to roll