日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

物理内存映射

發布時間:2024/1/8 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 物理内存映射 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
kernel 通過paging_init來映射物理內存 void __init paging_init(void) {#為pgd申請內存并賦值,這時候還沒有buddy system,因此在早期都是通過memblock來申請內存的phys_addr_t pgd_phys = early_pgtable_alloc();pgd_t *pgdp = pgd_set_fixmap(pgd_phys);#可以看到kernel本身占用的內存是單獨映射的,這兩個函數我們后面詳細分析map_kernel(pgdp);map_mem(pgdp);#在head.s中有申請一段memory來臨時映射物理內存swapper_pg_dir,這里我們可以復用#這段內存,這樣我們就可以把通過memblock申請的pgd_phys 釋放掉cpu_replace_ttbr1(__va(pgd_phys));memcpy(swapper_pg_dir, pgdp, PGD_SIZE);cpu_replace_ttbr1(lm_alias(swapper_pg_dir));pgd_clear_fixmap();#釋放pgd_phys 占用的內存memblock_free(pgd_phys, PAGE_SIZE);/** We only reuse the PGD from the swapper_pg_dir, not the pud + pmd* allocated with it.*/#我們只是復用swapper_pg_dir 中pgd的memory,因此治理釋放到pud和pmd 占用的內存memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,__pa_symbol(swapper_pg_end) - __pa_symbol(swapper_pg_dir)- PAGE_SIZE); } 首先看看map_kernel static void __init map_kernel(pgd_t *pgdp) {static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_inittext,vmlinux_initdata, vmlinux_data;pgprot_t text_prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;#從下面這段可以看出kernel 本身占用的memory可以分為下面這5段map_kernel_segment(pgdp, _text, _etext, text_prot, &vmlinux_text, 0,VM_NO_GUARD);map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL,&vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD);map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot,&vmlinux_inittext, 0, VM_NO_GUARD);map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL,&vmlinux_initdata, 0, VM_NO_GUARD);map_kernel_segment(pgdp, _data, _end, PAGE_KERNEL, &vmlinux_data, 0, 0);#最終map_kernel_segment->__create_pgd_mapping->pud->pmd->pte等來映射 } memblock 中的memory映射如下: static void __init map_mem(pgd_t *pgdp) {phys_addr_t kernel_start = __pa_symbol(_text);phys_addr_t kernel_end = __pa_symbol(__init_begin);struct memblock_region *reg;int flags = 0;#是否開debug選項if (debug_pagealloc_enabled())flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;/** Take care not to create a writable alias for the* read-only text and rodata sections of the kernel image.* So temporarily mark them as NOMAP to skip mappings in* the following for-loop*/#由于kernel 占用的memory頁包含在memblock中,且我們再前面已經映射kernel了,所以#這里標記kernel占用的memory不用在重復映射了memblock_mark_nomap(kernel_start, kernel_end - kernel_start); #ifdef CONFIG_KEXEC_COREif (crashk_res.end)memblock_mark_nomap(crashk_res.start,resource_size(&crashk_res)); #endif/* map all the memory banks */#開始映射memblock中的memoryfor_each_memblock(memory, reg) {phys_addr_t start = reg->base;phys_addr_t end = start + reg->size;#起始地址大于結束地址的話,肯定更有問題,退出if (start >= end)break;#如果memblock包含MEMBLOCK_NOMAP,則不用映射,例如前面提到的kernel的映射if (memblock_is_nomap(reg))continue;#開始映射memblock中的memory__map_memblock(pgdp, start, end, PAGE_KERNEL, flags);}__map_memblock(pgdp, kernel_start, kernel_end,PAGE_KERNEL, NO_CONT_MAPPINGS);#清除kernel memory段的MEMBLOCK_NOMAPmemblock_clear_nomap(kernel_start, kernel_end - kernel_start);}

總結

以上是生活随笔為你收集整理的物理内存映射的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。