Skip to content

NEMU 内存占用调参备忘

Wonicon edited this page Jul 27, 2016 · 1 revision

由于 Nexys4 DDR 上存储资源十分有限,需要调整 NEMU, 内核以及测试程序的一些参数来控制其内存使用。 这一块牵连较多,暂时没有形成很好的依赖关系,所以只能手工操作,备忘如下。

NEMU 的 dram 数组大小

dram 数组用于模拟 dram 存储器,是内存消耗的大头。 在 NEMU/src/memory/dram.c 中有其尺寸的设定:

#define COL_WIDTH 9
#define ROW_WIDTH 9
#define BANK_WIDTH 2
#define RANK_WIDTH (22 - COL_WIDTH - ROW_WIDTH - BANK_WIDTH)

其中 22 是 dram 总的地址宽度,即总容量是 (1 << 22) = 4 MiB. 要修改 dram 的总容量,减少内存占用,只需要调整该数值,并保证 COL, ROW, BANK 的宽度和不超过即可。 这个数字需要大于内核的 start.S 里设置的栈的起始地址。

$esp 的起始位置

在实模式的 NEMU 下,$esp 的起始地址往往代表了整个模拟系统最大的内存地址空间。它在两处进行设置:

NEMU/kernel/start/start.S. 内核初始化时首先会设置 $esp 的值以维护栈空间。 与上文对应的 $esp 的设置如下:

start:
# Set up a stack for C code.
    movl $0, %ebp
    movl $(1 << 22), %esp
    jmp init                # never return

NEMU/src/cpu/cpu-exec.c. 在 restart() 函数里,会对 cpu.esp 进行硬件层面的初始化。 不过这个值往往立刻被内核代码覆写,所以不需要太在意。

内核地址空间

内核地址空间的上限视实现而定,下限要考虑到硬件的一些内存映射约定。 类似于 BIOS, NEMU 首先想内核加载到确定的地址,然后从物理意义上的首地址开始执行。 要修改内核的首地址,如设置成 0x100000,需要修改 NEMU/kernel/kern.ld 里的起始地址,如下所示:

ENTRY(start)
SECTIONS
{
    . = 0x00100000;
    .text : { *(.text) }
    .data : { *(.data) }
    .bss  : { *(.bss)  }
}

还要修改 NEMU/src/cpu/cpu-exec.c 中的宏 LOADER_START, 设置成相同的值。

测试程序地址空间

在实模式的 NEMU 以及配套的内核下,测试程序的 ELF 文件声称其地址空间是什么范围,我们就把它往对应的 dram 位置放。 所以,只需要修改 testcase 目录下对应测试程序的 Makefile, 在 ld 的选项上添加 -Ttext=... 来设置自己需要的起始地址。