mm/cma.c

Source file repositories/reference/linux-study-clean/mm/cma.c

File Facts

System
Linux kernel
Corpus path
mm/cma.c
Extension
.c
Size
30137 bytes
Lines
1150
Domain
Core OS
Bucket
Memory Management
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

core_initcall(cma_init_reserved_areas);

void __init cma_reserve_pages_on_error(struct cma *cma)
{
	set_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags);
}

static int __init cma_new_area(const char *name, phys_addr_t size,
			       unsigned int order_per_bit,
			       struct cma **res_cma)
{
	struct cma *cma;

	if (cma_area_count == ARRAY_SIZE(cma_areas)) {
		pr_err("Not enough slots for CMA reserved regions!\n");
		return -ENOSPC;
	}

	/*
	 * Each reserved area must be initialised later, when more kernel
	 * subsystems (like slab allocator) are available.
	 */
	cma = &cma_areas[cma_area_count];
	cma_area_count++;

	if (name)
		strscpy(cma->name, name);
	else
		snprintf(cma->name, CMA_MAX_NAME,  "cma%d\n", cma_area_count);

	cma->available_count = cma->count = size >> PAGE_SHIFT;
	cma->order_per_bit = order_per_bit;
	*res_cma = cma;
	totalcma_pages += cma->count;

	return 0;
}

static void __init cma_drop_area(struct cma *cma)
{
	totalcma_pages -= cma->count;
	cma_area_count--;
}

/**
 * cma_init_reserved_mem() - create custom contiguous area from reserved memory
 * @base: Base address of the reserved area
 * @size: Size of the reserved area (in bytes),
 * @order_per_bit: Order of pages represented by one bit on bitmap.
 * @name: The name of the area. If this parameter is NULL, the name of
 *        the area will be set to "cmaN", where N is a running counter of
 *        used areas.
 * @res_cma: Pointer to store the created cma region.
 *
 * This function creates custom contiguous area from already reserved memory.
 */
int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
				 unsigned int order_per_bit,
				 const char *name,
				 struct cma **res_cma)
{
	struct cma *cma;
	int ret;

	/* Sanity checks */
	if (!size || !memblock_is_region_reserved(base, size))
		return -EINVAL;

	/*
	 * CMA uses CMA_MIN_ALIGNMENT_BYTES as alignment requirement which
	 * needs pageblock_order to be initialized. Let's enforce it.
	 */
	if (!pageblock_order) {
		pr_err("pageblock_order not yet initialized. Called during early boot?\n");
		return -EINVAL;
	}

	/* ensure minimal alignment required by mm core */
	if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
		return -EINVAL;

	ret = cma_new_area(name, size, order_per_bit, &cma);
	if (ret != 0)
		return ret;

	cma->ranges[0].base_pfn = PFN_DOWN(base);
	cma->ranges[0].early_pfn = PFN_DOWN(base);
	cma->ranges[0].count = cma->count;
	cma->nranges = 1;
	cma->nid = NUMA_NO_NODE;

Annotation

Implementation Notes