Linux reserved memory分析

来源:互联网 发布:污网络用语是啥意思 编辑:程序博客网 时间:2024/05/28 22:09

arch/arm/kernel/setup.c

void __init setup_arch(char **cmdline_p){arm_memblock_init(mdesc);paging_init(mdesc);}

void __init arm_memblock_init(const struct machine_desc *mdesc){early_init_fdt_reserve_self();early_init_fdt_scan_reserved_mem();}

/** * early_init_fdt_scan_reserved_mem() - create reserved memory regions * * This function grabs memory from early allocator for device exclusive use * defined in device tree structures. It should be called by arch specific code * once the early allocator (i.e. memblock) has been fully activated. */void __init early_init_fdt_scan_reserved_mem(void){int n;u64 base, size;if (!initial_boot_params)return;/* Process header /memreserve/ fields */for (n = 0; ; n++) {fdt_get_mem_rsv(initial_boot_params, n, &base, &size);if (!size)break;early_init_dt_reserve_memory_arch(base, size, 0);}of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);fdt_init_reserved_mem();}

of_scan_flat_dt是for循环遍历所有可能持有memory-region的节点,调用函数是__fdt_scan_reserved_mem

/** * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory */static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,  int depth, void *data){static int found;const char *status;int err;if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) {if (__reserved_mem_check_root(node) != 0) {pr_err("Reserved memory: unsupported node format, ignoring\n");/* break scan */return 1;}found = 1;//第一遍查找,找到"reserved-memory"并检查合法性/* scan next node */return 0;//完成第一遍查找任务} else if (!found) {/* scan next node */return 0;//现在是第二遍从查找,found=0表示第一遍没有找到"reserved-memory"所以宣布失败} else if (found && depth < 2) {/* scanning of /reserved-memory has been finished */return 1;}status = of_get_flat_dt_prop(node, "status", NULL);//如果有使用status,除了okay ok,其他字符串都表示disableif (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0)return 0;err = __reserved_mem_reserve_reg(node, uname);//核心reserve函数,需要有reg属性if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL))fdt_reserved_mem_save_node(node, uname, 0, 0);/* scan next node */return 0;}


drivers/of/fdt.c

int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,phys_addr_t size, bool nomap){if (nomap)return memblock_remove(base, size);return memblock_reserve(base, size);}

到此,scan的工作完成了,下一个函数是init这些reserved memroy,重新回顾下

void __init early_init_fdt_scan_reserved_mem(void){of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);fdt_init_reserved_mem();}

void __init fdt_init_reserved_mem(void){int i;/* check for overlapping reserved regions */__rmem_check_for_overlap();for (i = 0; i < reserved_mem_count; i++) {struct reserved_mem *rmem = &reserved_mem[i];unsigned long node = rmem->fdt_node;int len;const __be32 *prop;int err = 0;prop = of_get_flat_dt_prop(node, "phandle", &len);//memory region是通过phandle匹配,phandle就是设备持有的if (!prop)prop = of_get_flat_dt_prop(node, "linux,phandle", &len);if (prop)rmem->phandle = of_read_number(prop, len/4);if (rmem->size == 0)err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size);if (err == 0)__reserved_mem_init_node(rmem);}}

/** * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' *  and 'alloc-ranges' properties */static int __init __reserved_mem_alloc_size(unsigned long node,const char *uname, phys_addr_t *res_base, phys_addr_t *res_size){ret = early_init_dt_alloc_reserved_memory_arch(size,align, start, end, nomap, &base);}



预留CMA的reserved memory

static int __init rmem_cma_setup(struct reserved_mem *rmem){phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);phys_addr_t mask = align - 1;unsigned long node = rmem->fdt_node;struct cma *cma;int err;if (!of_get_flat_dt_prop(node, "reusable", NULL) ||    of_get_flat_dt_prop(node, "no-map", NULL))return -EINVAL;if ((rmem->base & mask) || (rmem->size & mask)) {pr_err("Reserved memory: incorrect alignment of CMA region\n");return -EINVAL;}err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);if (err) {pr_err("Reserved memory: unable to setup CMA region\n");return err;}/* Architecture specific contiguous memory fixup. */dma_contiguous_early_fixup(rmem->base, rmem->size);if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))dma_contiguous_set_default(cma);rmem->ops = &rmem_cma_ops;rmem->priv = cma;pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",&rmem->base, (unsigned long)rmem->size / SZ_1M);return 0;}RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);

节点要定义"shared-dma-pool",如

reserved-memory {#address-cells = <1>;#size-cells = <1>;ranges;cma_region: region@6a000000 {compatible = "shared-dma-pool";no-map;reg = <0x6a000000 0x1000000>;linux,cma-default;};




原创粉丝点击