git: 5ae2e6f913fa - main - LinuxKPI: Add bitmap_intersects(), bitmap_from_arr32()

From: Vladimir Kondratyev <wulf_at_FreeBSD.org>
Date: Sun, 24 Dec 2023 08:23:13 UTC
The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=5ae2e6f913fa1df5f3262255558b76af05409a09

commit 5ae2e6f913fa1df5f3262255558b76af05409a09
Author:     Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2023-12-24 08:19:59 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2023-12-24 08:19:59 +0000

    LinuxKPI: Add bitmap_intersects(), bitmap_from_arr32()
    
    and bitmap_shift_right() functions to linux/bitmap.h
    
    They perform calculation of two bitmaps intersection,
    copying the contents of u32 array of bits to bitmap and
    logical right shifting of the bits in a bitmap.
    
    Sponsored by:   Serenity Cyber Security, LLC
    Reviewed by:    manu
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42812
---
 sys/compat/linuxkpi/common/include/linux/bitmap.h | 78 +++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/bitmap.h b/sys/compat/linuxkpi/common/include/linux/bitmap.h
index 85cef18ec14a..84e0ba9c88ca 100644
--- a/sys/compat/linuxkpi/common/include/linux/bitmap.h
+++ b/sys/compat/linuxkpi/common/include/linux/bitmap.h
@@ -264,6 +264,27 @@ bitmap_subset(const unsigned long *pa,
 	return (1);
 }
 
+static inline bool
+bitmap_intersects(const unsigned long *pa, const unsigned long *pb,
+    unsigned size)
+{
+	const unsigned end = BIT_WORD(size);
+	const unsigned tail = size & (BITS_PER_LONG - 1);
+	unsigned i;
+
+	for (i = 0; i != end; i++)
+		if (pa[i] & pb[i])
+			return (true);
+
+	if (tail) {
+		 const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
+
+		if (pa[end] & pb[end] & mask)
+			return (true);
+	}
+	return (false);
+}
+
 static inline void
 bitmap_complement(unsigned long *dst, const unsigned long *src,
     const unsigned int size)
@@ -306,6 +327,29 @@ bitmap_to_arr32(uint32_t *dst, const unsigned long *src, unsigned int size)
 		dst[end - 1] &= (uint32_t)(UINT_MAX >> (32 - (size % 32)));
 }
 
+static inline void
+bitmap_from_arr32(unsigned long *dst, const uint32_t *src,
+    unsigned int size)
+{
+	const unsigned int end = BIT_WORD(size);
+	const unsigned int tail = size & (BITS_PER_LONG - 1);
+
+#ifdef __LP64__
+	const unsigned int end32 = howmany(size, 32);
+	unsigned int i = 0;
+
+	while (i < end32) {
+		dst[i++/2] = (unsigned long) *(src++);
+		if (i < end32)
+			dst[i++/2] |= ((unsigned long) *(src++)) << 32;
+	}
+#else
+	bitmap_copy(dst, (unsigned long *)src, size);
+#endif
+	if ((size % BITS_PER_LONG) != 0)
+		dst[end] &= BITMAP_LAST_WORD_MASK(tail);
+}
+
 static inline void
 bitmap_or(unsigned long *dst, const unsigned long *src1,
     const unsigned long *src2, const unsigned int size)
@@ -350,6 +394,40 @@ bitmap_xor(unsigned long *dst, const unsigned long *src1,
 		dst[i] = src1[i] ^ src2[i];
 }
 
+static inline void
+bitmap_shift_right(unsigned long *dst, const unsigned long *src,
+    unsigned int shift, unsigned int size)
+{
+	const unsigned int end = BITS_TO_LONGS(size);
+	const unsigned int tail = size & (BITS_PER_LONG - 1);
+	const unsigned long mask = BITMAP_LAST_WORD_MASK(tail);
+	const unsigned int off = BIT_WORD(shift);
+	const unsigned int rem = shift & (BITS_PER_LONG - 1);
+	unsigned long left, right;
+	unsigned int i, srcpos;
+
+	for (i = 0, srcpos = off; srcpos < end; i++, srcpos++) {
+		right = src[srcpos];
+		left = 0;
+
+		if (srcpos == end - 1)
+			right &= mask;
+
+		if (rem != 0) {
+			right >>= rem;
+			if (srcpos + 1 < end) {
+				left = src[srcpos + 1];
+				if (srcpos + 1 == end - 1)
+					left &= mask;
+				left <<= (BITS_PER_LONG - rem);
+			}
+		}
+		dst[i] = left | right;
+	}
+	if (off != 0)
+		memset(dst + end - off, 0, off * sizeof(unsigned long));
+}
+
 static inline unsigned long *
 bitmap_alloc(unsigned int size, gfp_t flags)
 {