以cma的early_param分析下early_param这个宏。
drivers/base/dma-contiguous.c定义了
static int __init early_cma(char *p)
{
pr_debug("%s(%s)\n", __func__, p);
size_cmdline = memparse(p, &p);
return 0;
}
early_param("cma", early_cma);
early_param是一个宏:
/* NOTE: fn is as per module_param, not __setup! Emits warning if fn
* returns non-zero. */
#define early_param(str, fn) \
__setup_param(str, fn, fn, 1)
/*
* Only for really core code. See moduleparam.h for the normal way.
*
* Force the alignment so the compiler doesn't space elements of the
* obs_kernel_param "array" too far apart in .init.setup.
*/
#define __setup_param(str, unique_id, fn, early) \
static const char __setup_str_##unique_id[] __initconst \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__used __section(.init.setup) \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }
展开后:
struct obs_kernel_param __setup_early_cma
__used __section(.init.setup)
__attribute__((aligned((sizeof(long)))))
= { "cma", early_cma, 1}
include/asm-generic/vmlinux.lds.h +628 定义了
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
*(.init.setup) \
VMLINUX_SYMBOL(__setup_end) = .;
.init.setup段的开始和结束分别用__setup_start和__setup_end表示。
Kernel中有很多类似的声明,这些结构体变量被保存在 .init.setup段中。
Kernel初始化时
Start_kernel—-> parse_early_param—->parse_early_options—-> do_early_param
该函数会遍历 __setup_start和 __setup_end之间的所有结构体,然后将 cmdline中的各个参数与字符串 ”cma”比较,如果匹配,那么调用 early_cma函数。