從零分配內存
阿新 • • 發佈:2018-03-30
tab log ati end 指令 text pagetable boot u-boot
1.解壓縮內核階段,對整個4G的虛擬內存做1:1映射,只一級映射,一個頁表項對應1MB,
共4096個頁表項,一級頁表占用16KB內存空間。
/*arch/arm/boot/compressed/head.S中*/ start -->__setup_mmu
2. 解壓後,打開MMU之前.映射當前執行的指令所在地址pa的1MB的地址。
映射KERNEL_START~KERNEL_END間的地址到pa起的物理地址
L1pagetable_addr PA VA 0x5000_5400 0x5000_0000 0x5000_0000 .... ... ... 0x5000_7000 0x5000_0000 0xC000_0000 KERNEL_START 0x5000_7004 0x5010_0000 0xC010_0000 ... 0x5000_7008 0x5020_0000 0xC020_0000 ... 0x5000_700c 0x5030_0000 0xC030_0000 ... 0x5000_7010 0x5040_0000 0xC040_0000 KERNEL_END
/*arch/arm/kernel/head.S*/ stext -->__create_page_tables
3. 內存信息如何傳入到內存管理系統
由u-boot通過struct tag結構傳入內核,約定好存放地址,譬如0x5000_0100
解析參數中的ATAG_MEM類型的參數
__tagtable(ATAG_MEM, parse_tag_mem32);
static int __init parse_tag_mem32(const struct tag *tag) -->arm_add_memory(tag->u.mem.start, tag->u.mem.size);-->struct membank *bank = &meminfo.bank[meminfo.nr_banks]; -->bank->start = PAGE_ALIGN(start); -->bank->size = size & PAGE_MASK; -->bank->node = PHYS_TO_NID(start); -->meminfo.nr_banks++;
內核中arch/arm/mm/init.c中定義全局變量struct meminfo meminfo,用於保存內存信息,如起始物理地址,內存大小即所屬的Node(用於NUMA)等
struct membank { unsigned long start; unsigned long size; int node; }; struct meminfo { int nr_banks; struct membank bank[NR_BANKS]; };
以OK6410為例,初始化之後
meminfo.nr_banks=1;
meminfo.bank[0].start = 0x5000_0000;
meminfo.bank[0].size = 0x1000_0000;//256M
meminfo.bank[0].node = 0;
4.boot_allocator的建立arch/arm/mm/mmu.c
void __init paging_init(struct machine_desc *mdesc) /*準備頁表,除meminfo。bank[0]定義的內存區域外全部映射都清零*/ -->void prepare_page_table(void) -->bootmem_init();
從零分配內存