memtest86+与BadRAM使用

memtest86+与BadRAM使用

一般情况下,DRAM的损坏是永久性的损坏,这个时候我们有三种方式解决这个问题:

我们这里使用第三种方式来绕过当前的内存坏块,而达到省钱的目的!badram 第一个参数 是出错的物理基地址,第二个参数是mask,来用标示这个掩码。当我们使用memtest86+测试出当前的出错内存物理地址,然后将这个错误地址加入到kernel 参数中即可。

其中memtest86+是一款离线内存检测工具,可以检测内存中的坏页。

下面我们来实验一下,比如当前系统没有出现内存坏块,那么使用iomem参看当前物理内存地址的分布:


00000000-00000fff : reserved
00001000-0009f3ff : System RAM
0009f400-0009ffff : reserved
000a0000-000bffff : PCI Bus 0000:00
000c0000-000dffff : PCI Bus 0000:00
  000c0000-000c7fff : Video ROM
  000cc000-000cd7ff : Adapter ROM
000e0000-000effff : pnp 00:08
000f0000-000fffff : reserved
  000f0000-000fffff : System ROM
00100000-7f6dffff : System RAM
  01000000-017b9cc4 : Kernel code
  017b9cc5-01d1e8ff : Kernel data
  01e86000-01fc8fff : Kernel bss
....

当我们在grub中加入badram 0x01000000,0xfffffffc参数,也就意味着Kernel代码区的地址出现错误,而且错误大小是2bit,这个时候我们重新启动,再查看当前系统物理内存分布,我们会发现:


01000000-010003ff : RAM buffer
01000400-7f6dffff : System RAM
  02000000-027b9cc4 : Kernel code
  027b9cc5-02d1e8ff : Kernel data
  

kernel 的代码段避过了问题内存区域,我们查看__pa(x)最终调用__phys_addr_nodebug,而其中phys_base则是在real_mode下面被调用。


static inline unsigned long __phys_addr_nodebug(unsigned long x)
{
    unsigned long y = x - __START_KERNEL_map;
 
    /* use the carry flag to determine if x was  __START_KERNEL_map */
    x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));
 
    return x;
}

Real-mode code 在X+0x8000开始,X就是badram传入的offset!