Linux - 内存 - 预留内存占用分析

说明

  • Linux启动log中会显示平台的内存信息,公司SOC平台,物理DRAM实际size是128M,但是启动log中total size不足128MB,并且预留内存(82272K reserved)过多,启动log如下:
Memory: 48032K/130304K available (3478K kernel code, 500K rwdata, 1504K rodata, 124K init, 212K bss, 82272K reserved, 0K cma-reserved)
  • total size:130304K,预留size 82272K相减得到剩余size(48032K)。

分析

  • 平台使用memblock管理早期内存分配,打开memblock debug重启后,启动log如下:
memblock_reserve: [0x0000000080200000-0x00000000807bdfff] setup_bootmem+0x86/0x162
memblock_reserve: [0x0000000082dcd000-0x0000000082dd2fff] setup_bootmem+0xde/0x162
memblock_reserve: [0x0000000080000000-0x000000008007ffff] setup_bootmem+0x100/0x162
memblock_reserve: [0x0000000080000000-0x000000008007ffff] early_init_fdt_scan_reserved_mem+0x46/0x76
memblock_reserve: [0x0000000080000000-0x000000008003ffff] __fdt_scan_reserved_mem+0x20a/0x27a
memblock_reserve: [0x000000008377e000-0x000000008393ffff] fdt_init_reserved_mem+0x306/0x42a
memblock_reserve: [0x0000000083940000-0x0000000087f3ffff] fdt_init_reserved_mem+0x360/0x42a
Ion: Ion memory setup at 0x0000000083940000 size 70 MiB
OF: reserved mem: initialized node ion, compatible id ion-region
MEMBLOCK configuration:
 memory size = 0x0000000007f40000 reserved size = 0x0000000004e06000
 memory.cnt  = 0x1
 memory[0x0]	[0x0000000080000000-0x0000000087f3ffff], 0x0000000007f40000 bytes flags: 0x0
 reserved.cnt  = 0x4
 reserved[0x0]	[0x0000000080000000-0x000000008007ffff], 0x0000000000080000 bytes flags: 0x0
 reserved[0x1]	[0x0000000080200000-0x00000000807bdfff], 0x00000000005be000 bytes flags: 0x0
 reserved[0x2]	[0x0000000082dcd000-0x0000000082dd2fff], 0x0000000000006000 bytes flags: 0x0
 reserved[0x3]	[0x000000008377e000-0x0000000087f3ffff], 0x00000000047c2000 bytes flags: 0x0
memblock_reserve: [0x000000008377d000-0x000000008377dfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008377c000-0x000000008377cfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008377b000-0x000000008377bfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008377a000-0x000000008377afff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083779000-0x0000000083779fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083778000-0x0000000083778fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083777000-0x0000000083777fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083776000-0x0000000083776fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083775000-0x0000000083775fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083774000-0x0000000083774fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083773000-0x0000000083773fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083772000-0x0000000083772fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083771000-0x0000000083771fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083770000-0x0000000083770fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376f000-0x000000008376ffff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376e000-0x000000008376efff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376d000-0x000000008376dfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376c000-0x000000008376cfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376b000-0x000000008376bfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008376a000-0x000000008376afff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083769000-0x0000000083769fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083768000-0x0000000083768fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083767000-0x0000000083767fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083766000-0x0000000083766fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083765000-0x0000000083765fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083764000-0x0000000083764fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083763000-0x0000000083763fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083762000-0x0000000083762fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083761000-0x0000000083761fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083760000-0x0000000083760fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375f000-0x000000008375ffff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375e000-0x000000008375efff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375d000-0x000000008375dfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375c000-0x000000008375cfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375b000-0x000000008375bfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008375a000-0x000000008375afff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083759000-0x0000000083759fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083758000-0x0000000083758fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083757000-0x0000000083757fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083756000-0x0000000083756fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083755000-0x0000000083755fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083754000-0x0000000083754fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083753000-0x0000000083753fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083752000-0x0000000083752fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083751000-0x0000000083751fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083750000-0x0000000083750fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374f000-0x000000008374ffff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374e000-0x000000008374efff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374d000-0x000000008374dfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374c000-0x000000008374cfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374b000-0x000000008374bfff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008374a000-0x000000008374afff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083749000-0x0000000083749fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083748000-0x0000000083748fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083747000-0x0000000083747fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083746000-0x0000000083746fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083745000-0x0000000083745fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083744000-0x0000000083744fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083743000-0x0000000083743fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083742000-0x0000000083742fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083741000-0x0000000083741fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x0000000083740000-0x0000000083740fff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008373f000-0x000000008373ffff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008373e000-0x000000008373efff] memblock_alloc_range_nid+0x96/0xc2
memblock_reserve: [0x000000008373d000-0x000000008373dfff] memblock_alloc_range_nid+0x96/0xc2
Zone ranges:
  DMA32    [mem 0x0000000080000000-0x0000000087f3ffff]
  Normal   empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000080000000-0x0000000087f3ffff]
Initmem setup node 0 [mem 0x0000000080000000-0x0000000087f3ffff]
On node 0 totalpages: 32576
memblock_alloc_try_nid: 1835008 bytes align=0x40 nid=0 from=0x0000000000000000 max_addr=0x0000000000000000 alloc_node_mem_map.constprop.0+0x4c/0xd0
memblock_reserve: [0x000000008357d000-0x000000008373cfff] memblock_alloc_range_nid+0x96/0xc2
  DMA32 zone: 446 pages used for memmap
  DMA32 zone: 0 pages reserved
  DMA32 zone: 32576 pages, LIFO batch:7
memblock_alloc_try_nid: 32 bytes align=0x40 nid=0 from=0x0000000000000000 max_addr=0x0000000000000000 setup_usemap.constprop.0+0x48/0x6c
memblock_reserve: [0x000000008357cfc0-0x000000008357cfdf] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 64 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 paging_init+0x228/0x2a2
memblock_reserve: [0x000000008357cf80-0x000000008357cfbf] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 96564 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565648-0x000000008357cf7b] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 44 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565618-0x0000000083565643] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 44 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x00000000835655e8-0x0000000083565613] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 44 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x00000000835655b8-0x00000000835655e3] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 44 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565588-0x00000000835655b3] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 44 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565558-0x0000000083565583] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 47 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565528-0x0000000083565556] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 47 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x00000000835654f8-0x0000000083565526] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 47 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x00000000835654c8-0x00000000835654f6] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 47 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565498-0x00000000835654c6] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 47 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565468-0x0000000083565496] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 49 bytes align=0x8 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 early_init_dt_alloc_memory_arch+0x16/0x3e
memblock_reserve: [0x0000000083565430-0x0000000083565460] memblock_alloc_range_nid+0x96/0xc2
SBI specification v0.3 detected
SBI implementation ID=0x1 Version=0x9
SBI v0.2 TIME extension detected
SBI v0.2 IPI extension detected
SBI v0.2 RFENCE extension detected
riscv: ISA extensions acdfimsuv
riscv: ELF capabilities acdfimv
memblock_alloc_try_nid: 229 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 start_kernel+0x82/0x346
memblock_reserve: [0x0000000083565340-0x0000000083565424] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 229 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 start_kernel+0xb2/0x346
memblock_reserve: [0x0000000083565240-0x0000000083565324] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 4096 bytes align=0x1000 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_alloc_alloc_info+0x44/0x78
memblock_reserve: [0x0000000083564000-0x0000000083564fff] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 32768 bytes align=0x1000 nid=-1 from=0x0000000080000000 max_addr=0x0000000000000000 setup_per_cpu_areas+0x2c/0x66
memblock_reserve: [0x000000008355c000-0x0000000083563fff] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 8 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_setup_first_chunk+0x13a/0x36e
memblock_reserve: [0x0000000083565200-0x0000000083565207] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 8 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_setup_first_chunk+0x168/0x36e
memblock_reserve: [0x00000000835651c0-0x00000000835651c7] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 4 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_setup_first_chunk+0x178/0x36e
memblock_reserve: [0x0000000083565180-0x0000000083565183] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 8 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_setup_first_chunk+0x188/0x36e
memblock_reserve: [0x0000000083565140-0x0000000083565147] memblock_alloc_range_nid+0x96/0xc2
pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
pcpu-alloc: [0] 0 
memblock_alloc_try_nid: 240 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_setup_first_chunk+0x224/0x36e
memblock_reserve: [0x0000000083565040-0x000000008356512f] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 128 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_alloc_first_chunk+0x5c/0x19a
memblock_reserve: [0x000000008355bf80-0x000000008355bfff] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 1024 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_alloc_first_chunk+0xa4/0x19a
memblock_reserve: [0x000000008355bb80-0x000000008355bf7f] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 1032 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_alloc_first_chunk+0xc2/0x19a
memblock_reserve: [0x000000008355b740-0x000000008355bb47] memblock_alloc_range_nid+0x96/0xc2
memblock_alloc_try_nid: 256 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 pcpu_alloc_first_chunk+0xd8/0x19a
memblock_reserve: [0x000000008355b640-0x000000008355b73f] memblock_alloc_range_nid+0x96/0xc2
memblock_free: [0x0000000083564000-0x0000000083564fff] start_kernel+0xe0/0x346
Built 1 zonelists, mobility grouping on.  Total pages: 32130
Kernel command line: rootfstype=squashfs rootwait ro root=/dev/mtdblock4 mtdparts=10000000.cvi-spif:1024K(fip),3072K(BOOT),64K(ENV),64K(ENV_BAK),10240K(ROOTFS),512K(DATA) console=ttyS0,115200 earlycon=sbi loglevel=9 riscv.fwsz=0x80000 memblock=debug
memblock_alloc_try_nid: 131072 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 alloc_large_system_hash+0x108/0x1d0
memblock_reserve: [0x000000008353b640-0x000000008355b63f] memblock_alloc_range_nid+0x96/0xc2
Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
memblock_alloc_try_nid: 65536 bytes align=0x40 nid=-1 from=0x0000000000000000 max_addr=0x0000000000000000 alloc_large_system_hash+0x108/0x1d0
memblock_reserve: [0x000000008352b640-0x000000008353b63f] memblock_alloc_range_nid+0x96/0xc2
Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
Sorting __ex_table...
mem auto-init: stack:off, heap alloc:off, heap free:off
Memory: 48032K/130304K available (3478K kernel code, 500K rwdata, 1504K rodata, 124K init, 212K bss, 82272K reserved, 0K cma-reserved)
...

total size由来

  • Linux感知的内存total size,可以通过uboot bootargs传递也可以通过dts配置,公司SOC使用dts配置,如下:
//file: xxx.dtsi 

#include 

/ {
    memory@80000000 {
            device_type = "memory";
            reg = <0x00 XXXMMAP_KERNEL_MEMORY_ADDR 0x00 XXXMMAP_KERNEL_MEMORY_SIZE>;
    };
    ....
};
  • 为兼容多个平台,dts中使用头文件中的宏定义来定义物理内存地址和大小,头文件由脚本生成,如下:
//file: memmap.py
    DRAM_BASE = 0x80000000
    DRAM_SIZE = 128 * SIZE_1M
    
    # 小核预留
    FREERTOS_SIZE = 768 * SIZE_1K
    
    ....

    # =========================
    # memory@DRAM_BASE in .dts.
    # =========================
    # Ignore the area of FreeRTOS in u-boot and kernel
    KERNEL_MEMORY_ADDR = DRAM_BASE
    KERNEL_MEMORY_SIZE = DRAM_SIZE - FREERTOS_SIZE
  • 因此kernel感知的实际total size(128MB * 1024 - 768 = 130304K)与启动log匹配。

memblock分配器初始化前的预留内存占用

  • memblock初始化成功的配置
MEMBLOCK configuration:
 memory size = 0x0000000007f40000 reserved size = 0x0000000004e06000 //总size(130304K)和初始化前的预留内存占用size
 memory.cnt  = 0x1
 memory[0x0]	[0x0000000080000000-0x0000000087f3ffff], 0x0000000007f40000 bytes flags: 0x0 //总size(130304K)
 reserved.cnt  = 0x4  // 初始化前的预留内存占用
 reserved[0x0]	[0x0000000080000000-0x000000008007ffff], 0x0000000000080000 bytes flags: 0x0
 reserved[0x1]	[0x0000000080200000-0x00000000807bdfff], 0x00000000005be000 bytes flags: 0x0
 reserved[0x2]	[0x0000000082dcd000-0x0000000082dd2fff], 0x0000000000006000 bytes flags: 0x0
 reserved[0x3]	[0x000000008377e000-0x0000000087f3ffff], 0x00000000047c2000 bytes flags: 0x0
  • 4块预留内存的详细分配记录(内存段相邻时会合并成一块)
memblock_reserve: [0x0000000080200000-0x00000000807bdfff] setup_bootmem+0x86/0x162
memblock_reserve: [0x0000000082dcd000-0x0000000082dd2fff] setup_bootmem+0xde/0x162
memblock_reserve: [0x0000000080000000-0x000000008007ffff] setup_bootmem+0x100/0x162
memblock_reserve: [0x0000000080000000-0x000000008007ffff] early_init_fdt_scan_reserved_mem+0x46/0x76
memblock_reserve: [0x0000000080000000-0x000000008003ffff] __fdt_scan_reserved_mem+0x20a/0x27a
memblock_reserve: [0x000000008377e000-0x000000008393ffff] fdt_init_reserved_mem+0x306/0x42a
memblock_reserve: [0x0000000083940000-0x0000000087f3ffff] fdt_init_reserved_mem+0x360/0x42a
  • 分配代码
//file: arch/riscv/mm/init.c
void __init setup_bootmem(void)
{
    phys_addr_t mem_start = 0;
    phys_addr_t start, end = 0;
    phys_addr_t vmlinux_end = __pa_symbol(&_end);
    phys_addr_t vmlinux_start = __pa_symbol(&_start);
    u64 i;

    /* Find the memory region containing the kernel */
    for_each_mem_range(i, &start, &end) {
        phys_addr_t size = end - start;
        if (!mem_start)
                mem_start = start;
        if (start <= vmlinux_start && vmlinux_end <= end)
                BUG_ON(size == 0);
    }

    /*
     * The maximal physical memory size is -PAGE_OFFSET.
     * Make sure that any memory beyond mem_start + (-PAGE_OFFSET) is removed
     * as it is unusable by kernel.
     */
    memblock_enforce_memory_limit(-PAGE_OFFSET);

    /* Reserve from the start of the kernel to the end of the kernel */
    memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);

    max_pfn = PFN_DOWN(memblock_end_of_DRAM());
    max_low_pfn = max_pfn;
    set_max_mapnr(max_low_pfn);

#ifdef CONFIG_BLK_DEV_INITRD
    setup_initrd();
#endif /* CONFIG_BLK_DEV_INITRD */

    /*
     * Avoid using early_init_fdt_reserve_self() since __pa() does
     * not work for DTB pointers that are fixmap addresses
     */
    memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));

    if (firmware_size > PAGE_SIZE && firmware_size < LOAD_OFFSET)
        memblock_reserve(__pa(PAGE_OFFSET), firmware_size);
    else
        memblock_reserve(__pa(PAGE_OFFSET), LOAD_OFFSET);
    
    ...
} 
  • 根据代码可知预留内存占用如下:
  1. kernel code等(大约6MB),大小是通过链接脚本ld.s中的符号(vmlinux_end,vmlinux_start)相减所得。
  2. opensbi(512KB),大小是通过uboot传递过来的bootargs(riscv.fwsz=0x80000)所得。
  3. dtb(32KB),大小:fdt_totalsize(dtb_early_va)
  4. dts中定义的ion(70MB)。
  5. dts中定义的其它reserved_mem(大约2MB),根据分配记录(memblock_reserve)可以获取分配的具体信息。

memblock分配器初始化后的预留内存占用

  • 启动log(MEMBLOCK configuration)后的分配打印就是memblock初始化成功后的预留内存占用。
  • 根据代码和分配记录可知预留内存占用主要是内核机制(大约2.3MB),有一些大头,如下:
  1. memmap
  2. setup_per_cpu_areas
  3. Dentry cache hash table entries
  4. Inode-cache hash table entries
  • 不同内核机制的分配,待分析。

预留内存占用统计

  • 将预留内存占用(memblock_reserve)累加再减去预留内存释放(memblock_free)计算出总的预留内存占用为82269K。

问题

  1. 统计出的总预留内存size和打印不匹配
  • 启动log中的预留内存总size(82272K reserved)和实际计算出的总size(82269K)不一致,是因为打印启动log时会做页对齐,对齐后就一样了,如下:
// file: linux_5.10/mm/page_alloc.c
void __init mem_init_print_info(const char *str)
{
    ...
    pr_info("Memory: %luK/%luK available (%luK kernel code, %luK rwdata, %luK rodata, %luK init, %luK bss, %luK reserved, %luK cma-reserved"
#ifdef  CONFIG_HIGHMEM
        ", %luK highmem"
#endif
        "%s%s)\n",
        nr_free_pages() << (PAGE_SHIFT - 10),
        physpages << (PAGE_SHIFT - 10),
        codesize >> 10, datasize >> 10, rosize >> 10,
        (init_data_size + init_code_size) >> 10, bss_size >> 10,
        (physpages - totalram_pages() - totalcma_pages) << (PAGE_SHIFT - 10), // 根据内存页size 对齐
        totalcma_pages << (PAGE_SHIFT - 10),
#ifdef  CONFIG_HIGHMEM
        totalhigh_pages() << (PAGE_SHIFT - 10),
#endif
        str ? ", " : "", str ? str : "");
}

你可能感兴趣的:(#,Linux,内核知识,linux)