内存管理-8-内存常用宏和全局变量
基于msm-5.4
一、常用宏
1. PAGE_OFFSET
线性映射的起始虚拟地址,TTBR1 地址空间的开始。默认是 0xffffff8000000000
//arch/arm64/include/asm/memory.h
#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS)) //-(1UL<<39)=0xffffff8000000000
补充:
PAGE_OFFSET 内核线性映射区的起始虚拟地址。
2. PAGE_END
线性映射的结束虚拟地址,其他映射从这里开始。默认是 0xffffffc000000000
//arch/arm64/include/asm/memory.h
#define PAGE_END (_PAGE_END(vabits_actual)) //-(1UL<<38) = 0xffffffc000000000
PAGE_END - PAGE_OFFSET = 256G
3. KIMAGE_VADDR
内核镜像的起始虚拟地址。其和 MODULES_END 相等,默认都是 0xffffffc010000000
//arch/arm64/include/asm/memory.h
define KIMAGE_VADDR (MODULES_END)
4. VA_BITS
虚拟地址的最大bit数,由 CONFIG_ARM64_VA_BITS 指定,默认值是39.
//arch/arm64/include/asm/memory.h
#define VA_BITS (CONFIG_ARM64_VA_BITS) //39
5. BPF_JIT_REGION_START
其和 KASAN_SHADOW_END 相等,默认都是 0xffffffc000000000
6. BPF_JIT_REGION_SIZE
默认是 0x8000000,即128M。
7. BPF_JIT_REGION_END
定义为 BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE 的值,默认是 0xffffffc008000000
8. MODULES_END
定义为 MODULES_VADDR + MODULES_VSIZE 的值,默认是 0xffffffc010000000
9. MODULES_VADDR
定义为 BPF_JIT_REGION_END 的值,默认是 0xffffffc008000000
10. MODULES_VSIZE
默认是 0x8000000,即128M。
11. VMEMMAP_START
默认值是 0xfffffffeffe00000
12. VMEMMAP_SIZE
默认是 0x100000000,即4G
13. PCI_IO_END
指定为 VMEMMAP_START - SZ_2M,默认是 0xfffffffeffc00000
14. PCI_IO_START
指定为 PCI_IO_END - PCI_IO_SIZE,默认是 0xfffffffefec00000,因此可得到 PCI_IO_SIZE 的大小为 0x1000000,即16M.
15. FIXADDR_TOP
指定为 PCI_IO_START - SZ_2M,默认是 0xfffffffefea00000
16. PHYS_OFFSET
表示内存起始物理地址, 默认 0x80000000
//arch/arm64/include/asm/memory.h
#define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) //0x80000000
17. PGD_SIZE
打印是 0x1000
18. PUD_SHIFT
打印是 0x1e,即30.
//include/asm-generic/pgtable-nop4d-hack.h
#define PUD_SHIFT PGDIR_SHIFT //30
#define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS) //参数1, 结果是30
注:39bit的3级页表,不存在PUD页表项。
19. PUD_SIZE
打印是 0x40000000,
//include/asm-generic/pgtable-nop4d-hack.h
#define PUD_SIZE (1UL << PUD_SHIFT) //1<<30=0x40000000
注:39bit的3级页表,不存在PUD页表项。
20. PMD_SHIFT
打印是 0x15 即 21.
//arch/arm64/include/asm/pgtable-hwdef.h
#define PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2) //参数2, 结果是21
21. PMD_SIZE
打印是 0x200000
//arch/arm64/include/asm/pgtable-hwdef.h
#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) //1UL << 21 = 0x200000
22. P4D_SHIFT
23. P4D_SIZE
注:P4D_SHIFT P4D_SIZE 两个宏应该是没有定义的,其只在 5level-fixup.h pgtable-nop4d.h 两个头文件中定义,但是这两个头文件都没有被包含。
24. PAGE_SHIFT
打印是12
//arch/arm64/include/asm/page-def.h
#define PAGE_SHIFT CONFIG_ARM64_PAGE_SHIFT //12
25. PAGE_SIZE
打印是0x1000, 即4K
//arch/arm64/include/asm/page-def.h
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) //1UL<<12=4K
26. VMALLOC_START
定义了vmalloc区域的结束虚拟地址,打印是 0xffffffc010000000
//arch/arm64/include/asm/pgtable.h
#define VMALLOC_START (MODULES_END)
27. VMALLOC_END
定义了vmalloc区域的起始虚拟地址
//arch/arm64/include/asm/pgtable.h
#define VMALLOC_END (- PUD_SIZE - VMEMMAP_SIZE - SZ_64K) //(-0x40000000 - 0x100000000 - 0x00010000)=0xfffffff1bffe0000
28. STRUCT_PAGE_MAX_SHIFT
打印是 6
//include/linux/mm_types.h
#define STRUCT_PAGE_MAX_SHIFT (order_base_2(sizeof(struct page)))
29. XXX
30. MODULES_END
打印是 0xffffffc010000000
//arch/arm64/include/asm/memory.h
#define MODULES_END (MODULES_VADDR + MODULES_VSIZE) //0xffffffc008000000 + 0x08000000 = 0xffffffc010000000
31. MODULES_VADDR
打印值 0xffffffc008000000
//arch/arm64/include/asm/memory.h
#define MODULES_VADDR (BPF_JIT_REGION_END) //0xffffffc008000000
32. MODULES_VSIZE
打印值 0x8000000
//arch/arm64/include/asm/memory.h
#define MODULES_VSIZE (SZ_128M) //0x08000000
33. BPF_JIT_REGION_END
打印值 0xffffffc008000000
//arch/arm64/include/asm/memory.h
#define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE) //0xffffffc000000000 + 0x08000000 = 0xffffffc008000000
34. BPF_JIT_REGION_START
打印值 0xffffffc000000000
//arch/arm64/include/asm/memory.h
#define BPF_JIT_REGION_START (KASAN_SHADOW_END) //0xffffffc000000000
35. BPF_JIT_REGION_SIZE
打印值 0x8000000
//arch/arm64/include/asm/memory.h
#define BPF_JIT_REGION_SIZE (SZ_128M) //0x08000000
36. KASAN_SHADOW_END
打印值 0xffffffc000000000
//arch/arm64/include/asm/memory.h
#define KASAN_SHADOW_END (_PAGE_END(VA_BITS_MIN)) //_PAGE_END(39)=(-(1UL<<38))=0xffffffc000000000
37. VMEMMAP_START
vmmap区域的起始虚拟地址,打印值 0xfffffffeffe00000
//arch/arm64/include/asm/memory.h
#define VMEMMAP_START (-VMEMMAP_SIZE - SZ_2M) //0xfffffffeffe00000
38. VMEMMAP_SIZE
打印值 0x100000000, 即4G
//arch/arm64/include/asm/memory.h
//(0xffffffc000000000 - 0xffffff8000000000) >> (12 - 6) = 0x100000000 = 4G
#define VMEMMAP_SIZE ((_PAGE_END(VA_BITS_MIN) - PAGE_OFFSET) >> (PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT))
39. PCI_IO_START
打印值 0xfffffffefec00000
//arch/arm64/include/asm/memory.h
#define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) //0xfffffffefec00000
40. PCI_IO_END
打印值 0xfffffffeffc00000
//arch/arm64/include/asm/memory.h
#define PCI_IO_END (VMEMMAP_START - SZ_2M) //0xfffffffeffc00000
41. PCI_IO_SIZE
//arch/arm64/include/asm/memory.h
#define PCI_IO_SIZE SZ_16M //0x01000000
42. FIXADDR_TOP
打印值 0xfffffffefea00000
//arch/arm64/include/asm/memory.h
#define FIXADDR_TOP (PCI_IO_START - SZ_2M) //0xfffffffefea00000
43. PAGE_FRAG_CACHE_MAX_SIZE
打印值 0x8000
//include/linux/mm_types.h
//(32768 + (~PAGE_MASK)) & PAGE_MASK = (0x8000 + 0xfff) & 0xfffffffffffff000 = 0x8000
#define PAGE_FRAG_CACHE_MAX_SIZE __ALIGN_MASK(32768, ~PAGE_MASK) //x+mask & ~mask
44. PAGE_MASK
//arch/arm64/include/asm/page-def.h
#define PAGE_MASK (~(PAGE_SIZE-1)) //~(0x1000-1)=0xfffffffffffff000
45. PAGE_FRAG_CACHE_MAX_ORDER
打印值 3
//arch/arm64/include/asm/page-def.h
#define PAGE_FRAG_CACHE_MAX_ORDER get_order(PAGE_FRAG_CACHE_MAX_SIZE) //传参0x8000,对应2^3个页的大小
46. PAGE_END
//arch/arm64/include/asm/memory.h
#define PAGE_END (_PAGE_END(vabits_actual)) //-(1UL<<38) = 0xffffffc000000000
47. ARM64_MEMSTART_ALIGN
打印值 0x40000000
//arch/arm64/include/asm/kernel-pgtable.h
#define ARM64_MEMSTART_ALIGN (1UL << ARM64_MEMSTART_SHIFT) //1<<30
48. ARM64_MEMSTART_SHIFT
打印值 30
//arch/arm64/include/asm/kernel-pgtable.h
#define ARM64_MEMSTART_SHIFT PUD_SHIFT //30
49. SECTION_SIZE_BITS
打印值 30
//arch/arm64/include/asm/sparsemem.h
#define SECTION_SIZE_BITS CONFIG_HOTPLUG_SIZE_BITS //30
50. SWAPPER_INIT_MAP_SIZE
表示初始内核直接映射的大小
//arch/arm64/include/asm/kernel-pgtable.h
#define SWAPPER_INIT_MAP_SIZE (_AC(1, UL) << SWAPPER_TABLE_SHIFT) //1UL<<30=0x40000000=1G
51. PGDIR_SHIFT
表示顶层页表PGD的偏移,一二三级页表都存在。
//arch/arm64/include/asm/pgtable-hwdef.h
#define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS) //参数1, 结果是30
52. PGDIR_SIZE
表示一个PGD页表项可以映射内存的大小
//arch/arm64/include/asm/pgtable-hwdef.h
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) //1UL<<30
53. PTRS_PER_PTE
表示每个页表项能够映射的页面数量
//arch/arm64/include/asm/pgtable-hwdef.h
#define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3)) //1<<(12-3)=1<<9=512
54. SWAPPER_MM_MMUFLAGS
定义了要映射地址的memory attribute
//arch/arm64/include/asm/kernel-pgtable.h
//4<<2 | 1<<0|1<<10|3<<8
#define SWAPPER_MM_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS)
55. TEXT_OFFSET
内核镜像在内核虚拟地址空间中的起始偏移地址。
//msm-5.4/arch/arm64/Makefile
TEXT_OFFSET := 0x00080000
//vmlinux.lds.S 中指定 .head.text 段的起始地址
. = KIMAGE_VADDR + TEXT_OFFSET; //0xffffffc010000000 + 0x00080000 内核起始虚拟地址+偏移32K的位置(内核镜像前16K预留出来给初始化页表使用)
二、常用全局变量
1. physvirt_offset
打印出来是 0x8080000000
arm64_memblock_init //arch/arm64/mm/init.c physvirt_offset = PHYS_OFFSET - PAGE_OFFSET; //0x80000000 - 0xffffff8000000000 = 0x8080000000
2. memstart_addr
打印出来是 0x80000000,有资料说表示起始物理地址。
arm64_memblock_init //mm/init.c memstart_addr = round_down(memblock_start_of_DRAM(), ARM64_MEMSTART_ALIGN); //round_down(0x00000000aed01000,1<<30)=1<<30 memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size, ARM64_MEMSTART_ALIGN); memstart_addr -= ARM64_MEMSTART_ALIGN * ((range * memstart_offset_seed) >> 16);
3. kimage_vaddr
表示内核镜像的虚拟基地址,打印出来是 0xffffffc010000000
arch/arm64/kernel/head.S ENTRY(kimage_vaddr) .quad _text - TEXT_OFFSET @.quad 表示4个word,即8个字节 EXPORT_SYMBOL(kimage_vaddr)
4. kimage_voffset
表示内核映射虚拟地址和物理地址之间的偏移,打印出来是 0xffffffbf61200000
arch/arm64/kernel/head.S __primary_switched: str_l x4, kimage_voffset, x5 // physical mappings
str_l 的含义是把 x4 的值保存到变量 kimage_voffset,x5 是临时使用,用来保存 kimage_voffset 这个变量所在的页的地址。
5. vmemmap
物理页帧数组存放在这个指针位置,虚拟地址,打印出来是 0xfffffffefde00000
arm64_memblock_init //arch/arm64/mm/init.c //0xfffffffeffe00000-64*(0x80000000>>12)=0xfffffffeffe00000-0x4000000=0xfffffffefde00000 vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT));
注;指针类型相减,sizeof(struct page)=64,因此还要乘以64.
5. bootloader_memory_limit
bootloader施加的物理内存限制,打印出来是 0x878100000
arm64_memblock_init //mm/init.c /* 0x0000000800000000 + (0x00000008780fffff - 0x0000000800000000) + 1 = 0x878100000 */ bootloader_memory_limit = memblock_end_of_DRAM();
6. vabits_actual
打印出来值是 39
三、总结
CONFIG_ARM64_VA_BITS 虚拟地址位宽,默认39
四、头文件包含关系
//arch/arm64/include/asm/pgtable-types.h #if CONFIG_PGTABLE_LEVELS == 2 #define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopmd.h> #elif CONFIG_PGTABLE_LEVELS == 3 //是这个 #define __ARCH_USE_5LEVEL_HACK #include <asm-generic/pgtable-nopud.h> #elif CONFIG_PGTABLE_LEVELS == 4 #include <asm-generic/5level-fixup.h> #endif //include/asm-generic/pgtable-nopud.h #ifdef __ARCH_USE_5LEVEL_HACK //是这个 #include <asm-generic/pgtable-nop4d-hack.h> #else #include <asm-generic/pgtable-nop4d.h> //include/asm-generic/page.h //包含这个文件会编译报错 #ifdef CONFIG_MMU #error need to provide a real asm/page.h #endif
使用头文件: pgtable-nopud.h pgtable-nop4d-hack.h asm/page.h
没有使用头文件: pgtable-nopmd.h 5level-fixup.h pgtable-nop4d.h asm-generic/page.h
posted on 2024-06-28 00:47 Hello-World3 阅读(9) 评论(0) 编辑 收藏 举报