kernel/bpf/core.c

Source file repositories/reference/linux-study-clean/kernel/bpf/core.c

File Facts

System
Linux kernel
Corpus path
kernel/bpf/core.c
Extension
.c
Size
91685 bytes
Lines
3538
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct bpf_prog_pack {
	struct list_head list;
	void *ptr;
	unsigned long bitmap[];
};

void bpf_jit_fill_hole_with_zero(void *area, unsigned int size)
{
	memset(area, 0, size);
}

#define BPF_PROG_SIZE_TO_NBITS(size)	(round_up(size, BPF_PROG_CHUNK_SIZE) / BPF_PROG_CHUNK_SIZE)

static DEFINE_MUTEX(pack_mutex);
static LIST_HEAD(pack_list);

/* PMD_SIZE is not available in some special config, e.g. ARCH=arm with
 * CONFIG_MMU=n. Use PAGE_SIZE in these cases.
 */
#ifdef PMD_SIZE
/* PMD_SIZE is really big for some archs. It doesn't make sense to
 * reserve too much memory in one allocation. Hardcode BPF_PROG_PACK_SIZE to
 * 2MiB * num_possible_nodes(). On most architectures PMD_SIZE will be
 * greater than or equal to 2MB.
 */
#define BPF_PROG_PACK_SIZE (SZ_2M * num_possible_nodes())
#else
#define BPF_PROG_PACK_SIZE PAGE_SIZE
#endif

#define BPF_PROG_CHUNK_COUNT (BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE)

static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_insns)
{
	struct bpf_prog_pack *pack;
	int err;

	pack = kzalloc_flex(*pack, bitmap, BITS_TO_LONGS(BPF_PROG_CHUNK_COUNT));
	if (!pack)
		return NULL;
	pack->ptr = bpf_jit_alloc_exec(BPF_PROG_PACK_SIZE);
	if (!pack->ptr)
		goto out;
	bpf_fill_ill_insns(pack->ptr, BPF_PROG_PACK_SIZE);
	bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);

	set_vm_flush_reset_perms(pack->ptr);
	err = set_memory_rox((unsigned long)pack->ptr,
			     BPF_PROG_PACK_SIZE / PAGE_SIZE);
	if (err)
		goto out;
	list_add_tail(&pack->list, &pack_list);
	return pack;

out:
	bpf_jit_free_exec(pack->ptr);
	kfree(pack);
	return NULL;
}

void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
{
	unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size);
	struct bpf_prog_pack *pack;
	unsigned long pos;
	void *ptr = NULL;

	mutex_lock(&pack_mutex);
	if (size > BPF_PROG_PACK_SIZE) {
		size = round_up(size, PAGE_SIZE);
		ptr = bpf_jit_alloc_exec(size);
		if (ptr) {
			int err;

			bpf_fill_ill_insns(ptr, size);
			set_vm_flush_reset_perms(ptr);
			err = set_memory_rox((unsigned long)ptr,
					     size / PAGE_SIZE);
			if (err) {
				bpf_jit_free_exec(ptr);
				ptr = NULL;
			}
		}
		goto out;
	}
	list_for_each_entry(pack, &pack_list, list) {
		pos = bitmap_find_next_zero_area(pack->bitmap, BPF_PROG_CHUNK_COUNT, 0,
						 nbits, 0);
		if (pos < BPF_PROG_CHUNK_COUNT)
			goto found_free_area;

Annotation

Implementation Notes