美文网首页
amlogic linux系统下可用内存分析

amlogic linux系统下可用内存分析

作者: 叶迎宪 | 来源:发表于2023-02-08 21:36 被阅读0次

一块S905D3的板子,贴了4G的内存,但是在linux下只看到3456MB的可用内存,于是分析原因。

之前的文章也分析到,影响内存大小有两个地方,一是uboot中的 firmware/timing.c,这个定义对了uboot才可以正确分析出内存的大小。uboot启动的日志节选

auto size-- 65535DDR cs0 size: 2048MB
DDR cs1 size: 2048MB
DMC_DDR_CTRL: 00700024DDR size: 3928MB
...
U-Boot 2015.01 (Feb 09 2023 - 16:12:09)

DRAM:  3.8 GiB
...
libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND
[rsvmem] fdt set /reserved-memory/ramoops reg  error.
   Loading Ramdisk to 7f4c6000, end 7f7ff545 ... OK
   Loading Device Tree to 000000001ffe4000, end 000000001ffff66d ... OK
fdt_fixup_memory_banks, reg:0000000000000000

影响内存大小的第二个地方在dtb中。/memory@00000000/linux,usable-memory 会影响linux下可用内存的大小。如果在dts中,完全屏蔽了memory一段的设置,则linux看到的内存大小是3456MB。如果设置 linux,usable-memory = <0x0 0xf0000000>; 则linux看到的内存大小为3840MB。

内核文档中对于 usable-memory 的解析

  • linux,usable-memory : This property overrides the reg property.
    It can be used if the bootloader changes the reg property to
    improper values.

那就是说,如果dts中配置了 linux,usable-memory,内存大小以usable-memory的配置为准。如果dts中没有这个配置,则内存大小由bootloader填入memory的reg字段决定。

从上面的uboot日志中,可以看到 fdt_fixup_memory_banks, reg:0000000000000000 一段。其对应的代码位于 common/fdt_support.c

int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
        int err, nodeoffset;
        int len;
        const void *reg;

        u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */

        if (banks > MEMORY_BANKS_MAX) {
                printf("%s: num banks %d exceeds hardcoded limit %d."
                       " Recompile with higher MEMORY_BANKS_MAX?\n",
                       __FUNCTION__, banks, MEMORY_BANKS_MAX);
                return -1;
        }

        err = fdt_check_header(blob);
        if (err < 0) {
                printf("%s: %s\n", __FUNCTION__, fdt_strerror(err));
                return err;
        }

        /* find or create "/memory" node. */
        nodeoffset = fdt_find_or_add_subnode(blob, 0, "memory");
        if (nodeoffset < 0)
                        return nodeoffset;

        err = fdt_setprop(blob, nodeoffset, "device_type", "memory",
                        sizeof("memory"));
        if (err < 0) {
                printf("WARNING: could not set %s %s.\n", "device_type",
                                fdt_strerror(err));
                return err;
        }

        reg = fdt_getprop(blob, nodeoffset, "reg", NULL);
        printf("%s, reg:%p\n", __func__, reg);
        if (reg) {
                printf("DTS already have 'reg' property\n");
                return 0;
        }

        len = fdt_pack_reg(blob, tmp, start, size, banks);

        err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
        if (err < 0) {
                printf("WARNING: could not set %s %s.\n",
                                "reg", fdt_strerror(err));
                return err;
        }
        return 0;
}

基本没干啥,就是往dtb里面写入 /memory/reg 的信息。试了一下,添加打印信息,把 u64 start[], u64 size[] 都打印出来。
start=0 size=3623878656
size对应的十六进制为 d800 0000,很明显没到4G应有的1 0000 0000。为什么是这个值呢?需要进一步跟踪代码。先看什么地方调用了 fdt_fixup_memory_banks,在 arch/arm/lib/bootm-fdt.c

int arch_fixup_fdt(void *blob)
{
        bd_t *bd = gd->bd;
        int bank, ret;
        u64 start[CONFIG_NR_DRAM_BANKS];
        u64 size[CONFIG_NR_DRAM_BANKS];

        for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
                start[bank] = bd->bi_dram[bank].start;
                size[bank] = bd->bi_dram[bank].size;
        }

        ret = fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);

./board/amlogic/configs/g12a_u200_v1.h:#define CONFIG_NR_DRAM_BANKS 1

继续找什么地方设置了 bd->bi_dram,在 common/board_f.c 的 show_dram_config

#if defined(CONFIG_SYS_MEM_TOP_HIDE)
        if ((gd->bd->bi_dram[0].size+CONFIG_SYS_MEM_TOP_HIDE) > (0xE0000000UL)) {
                gd->bd->bi_dram[0].size = 0xE0000000UL - CONFIG_SYS_MEM_TOP_HIDE;
        }
#else
        if (gd->bd->bi_dram[0].size > (0xE0000000UL)) {
                gd->bd->bi_dram[0].size = 0xE0000000UL;
        }
#endif

./build/include/autoconf.mk:CONFIG_SYS_MEM_TOP_HIDE=0x08000000

因此 0xE0000000 - 0x08000000 = 0xD800 0000。为什么要限制这个内存大小呢?从uboot的代码修改记录找到的答案 https://github.com/khadas/u-boot/commit/106a245a7de2a0038f5db6ddcbc8bbe48c8bddfe
Problem:
g12a/b 4GB ddr use 3584M for cache alignment reason

好无语的限制

相关文章

网友评论

      本文标题:amlogic linux系统下可用内存分析

      本文链接:https://www.haomeiwen.com/subject/jtwqkdtx.html