cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

find.c (1918B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * MSB0 numbered special bitops handling.
      4 *
      5 * The bits are numbered:
      6 *   |0..............63|64............127|128...........191|192...........255|
      7 *
      8 * The reason for this bit numbering is the fact that the hardware sets bits
      9 * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
     10 * from the 'wrong end'.
     11 */
     12
     13#include <linux/compiler.h>
     14#include <linux/bitops.h>
     15#include <linux/export.h>
     16
     17unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
     18{
     19	const unsigned long *p = addr;
     20	unsigned long result = 0;
     21	unsigned long tmp;
     22
     23	while (size & ~(BITS_PER_LONG - 1)) {
     24		if ((tmp = *(p++)))
     25			goto found;
     26		result += BITS_PER_LONG;
     27		size -= BITS_PER_LONG;
     28	}
     29	if (!size)
     30		return result;
     31	tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
     32	if (!tmp)		/* Are any bits set? */
     33		return result + size;	/* Nope. */
     34found:
     35	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
     36}
     37EXPORT_SYMBOL(find_first_bit_inv);
     38
     39unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
     40				unsigned long offset)
     41{
     42	const unsigned long *p = addr + (offset / BITS_PER_LONG);
     43	unsigned long result = offset & ~(BITS_PER_LONG - 1);
     44	unsigned long tmp;
     45
     46	if (offset >= size)
     47		return size;
     48	size -= result;
     49	offset %= BITS_PER_LONG;
     50	if (offset) {
     51		tmp = *(p++);
     52		tmp &= (~0UL >> offset);
     53		if (size < BITS_PER_LONG)
     54			goto found_first;
     55		if (tmp)
     56			goto found_middle;
     57		size -= BITS_PER_LONG;
     58		result += BITS_PER_LONG;
     59	}
     60	while (size & ~(BITS_PER_LONG-1)) {
     61		if ((tmp = *(p++)))
     62			goto found_middle;
     63		result += BITS_PER_LONG;
     64		size -= BITS_PER_LONG;
     65	}
     66	if (!size)
     67		return result;
     68	tmp = *p;
     69found_first:
     70	tmp &= (~0UL << (BITS_PER_LONG - size));
     71	if (!tmp)		/* Are any bits set? */
     72		return result + size;	/* Nope. */
     73found_middle:
     74	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
     75}
     76EXPORT_SYMBOL(find_next_bit_inv);