ARM64 memblock init过程

来源:互联网 发布:淘宝女装店铺改卖男装 编辑:程序博客网 时间:2024/06/05 16:43

前面已经就memblock初始化过程中用到的添加,插入,合并memblock region的API进行了说明,今天将简单介绍一下arm64_memblock_init这个函数:

void __init arm64_memblock_init(void){const s64 linear_region_size = -(s64)PAGE_OFFSET;-----------------------(1)/* * Ensure that the linear region takes up exactly half of the kernel * virtual address space. This way, we can distinguish a linear address * from a kernel/module/vmalloc address by testing a single bit. */BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1));/* * Select a suitable value for the base of physical memory. */memstart_addr = round_down(memblock_start_of_DRAM(),   ARM64_MEMSTART_ALIGN);---------------------------(2)/* * Remove the memory that we will not be able to cover with the * linear mapping. Take care not to clip the kernel which may be * high in memory. */memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),ULLONG_MAX);-----------------------(3)if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {/* ensure that memstart_addr remains sufficiently aligned */memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size, ARM64_MEMSTART_ALIGN);memblock_remove(0, memstart_addr);}/* * Apply the memory limit if it was set. Since the kernel may be loaded * high up in memory, add back the kernel region that must be accessible * via the linear mapping. */if (memory_limit != (phys_addr_t)ULLONG_MAX) {memblock_mem_limit_remove_map(memory_limit);memblock_add(__pa(_text), (u64)(_end - _text));}if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {/* * Add back the memory we just removed if it results in the * initrd to become inaccessible via the linear mapping. * Otherwise, this is a no-op */u64 base = initrd_start & PAGE_MASK;u64 size = PAGE_ALIGN(initrd_end) - base;/* * We can only add back the initrd memory if we don't end up * with more memory than we can address via the linear mapping. * It is up to the bootloader to position the kernel and the * initrd reasonably close to each other (i.e., within 32 GB of * each other) so that all granule/#levels combinations can * always access both. */if (WARN(base < memblock_start_of_DRAM() || base + size > memblock_start_of_DRAM() +       linear_region_size,"initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) {initrd_start = 0;} else {memblock_remove(base, size); /* clear MEMBLOCK_ flags */memblock_add(base, size);memblock_reserve(base, size);}}if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {extern u16 memstart_offset_seed;u64 range = linear_region_size -    (memblock_end_of_DRAM() - memblock_start_of_DRAM());/* * If the size of the linear region exceeds, by a sufficient * margin, the size of the region that the available physical * memory spans, randomize the linear region as well. */if (memstart_offset_seed > 0 && range >= ARM64_MEMSTART_ALIGN) {range = range / ARM64_MEMSTART_ALIGN + 1;memstart_addr -= ARM64_MEMSTART_ALIGN * ((range * memstart_offset_seed) >> 16);}}/* * Register the kernel text, kernel data, initrd, and initial * pagetables with memblock. */memblock_reserve(__pa(_text), _end - _text);-----------------(4)#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start) {memblock_reserve(initrd_start, initrd_end - initrd_start);/* the generic initrd code expects virtual addresses */initrd_start = __phys_to_virt(initrd_start);initrd_end = __phys_to_virt(initrd_end);}#endifearly_init_fdt_scan_reserved_mem();-----------------------(5)/* 4GB maximum for 32-bit only capable devices */if (IS_ENABLED(CONFIG_ZONE_DMA))arm64_dma_phys_limit = max_zone_dma_phys();elsearm64_dma_phys_limit = PHYS_MASK + 1;dma_contiguous_reserve(arm64_dma_phys_limit);memblock_allow_resize();}
(1)初始化linear_region_size = 0x4000000000.

(2)初始化memstart_addr.

(3)清理整个物理内存中的memblock region.

(4)调用memblock_reserve添加kernel text, data, initrd, init段memblock region.

(5)遍历dts,获取需要reserve的memory,通过memblock_reserve()函数reserve所有的dts的reserve memory.

下一篇将讲述memory type和reserve type memblock的初始化


原创粉丝点击