内存管理-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. PGD​​IR_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编辑  收藏  举报

导航