lib/crc/tests/crc_kunit.c

Source file repositories/reference/linux-study-clean/lib/crc/tests/crc_kunit.c

File Facts

System
Linux kernel
Corpus path
lib/crc/tests/crc_kunit.c
Extension
.c
Size
12155 bytes
Lines
513
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: implementation source
Status
source implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

struct crc_variant {
	int bits;
	bool le;
	u64 poly;
	u64 (*func)(u64 crc, const u8 *p, size_t len);
};

static u32 rand32(void)
{
	return prandom_u32_state(&rng);
}

static u64 rand64(void)
{
	u32 n = rand32();

	return ((u64)n << 32) | rand32();
}

static u64 crc_mask(const struct crc_variant *v)
{
	return (u64)-1 >> (64 - v->bits);
}

/* Reference implementation of any CRC variant */
static u64 crc_ref(const struct crc_variant *v,
		   u64 crc, const u8 *p, size_t len)
{
	size_t i, j;

	for (i = 0; i < len; i++) {
		for (j = 0; j < 8; j++) {
			if (v->le) {
				crc ^= (p[i] >> j) & 1;
				crc = (crc >> 1) ^ ((crc & 1) ? v->poly : 0);
			} else {
				crc ^= (u64)((p[i] >> (7 - j)) & 1) <<
				       (v->bits - 1);
				if (crc & (1ULL << (v->bits - 1)))
					crc = ((crc << 1) ^ v->poly) &
					      crc_mask(v);
				else
					crc <<= 1;
			}
		}
	}
	return crc;
}

static int crc_suite_init(struct kunit_suite *suite)
{
	/*
	 * Allocate the test buffer using vmalloc() with a page-aligned length
	 * so that it is immediately followed by a guard page.  This allows
	 * buffer overreads to be detected, even in assembly code.
	 */
	test_buflen = round_up(CRC_KUNIT_MAX_LEN, PAGE_SIZE);
	test_buffer = vmalloc(test_buflen);
	if (!test_buffer)
		return -ENOMEM;

	prandom_seed_state(&rng, CRC_KUNIT_SEED);
	prandom_bytes_state(&rng, test_buffer, test_buflen);
	return 0;
}

static void crc_suite_exit(struct kunit_suite *suite)
{
	vfree(test_buffer);
	test_buffer = NULL;
}

/* Generate a random initial CRC. */
static u64 generate_random_initial_crc(const struct crc_variant *v)
{
	switch (rand32() % 4) {
	case 0:
		return 0;
	case 1:
		return crc_mask(v); /* All 1 bits */
	default:
		return rand64() & crc_mask(v);
	}
}

/* Generate a random length, preferring small lengths. */
static size_t generate_random_length(size_t max_length)
{
	size_t len;

Annotation

Implementation Notes