我如何告诉 ubuntu 不要使用某些内存地址?

我如何告诉 ubuntu 不要使用某些内存地址?

如果措辞不当,我很抱歉,但我在我的一台电脑上做过内存测试,某些内存地址有错误。这是我第一次搜索。如果你需要更多信息,我可以提供。

答案1

如果您查看/etc/default/grub,您会发现一个GRUB_BADRAM=参数,您可以通过它识别存在哪些坏的内存位置。

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

设置完地址后,运行sudo update-grub即可应用。

笔记: 那GRUB_BADRAM 不起作用内核锁定(如果您启用了安全启动,此功能将被启用)。您可以通过运行来检查是否启用了安全启动mokutil --sb-state


取自https://help.ubuntu.com/community/BadRAM#BADRAM_setting_in_Grub2...

Grub2 中的 BADRAM 设置

Natty 中的 GRUB2 配置文件中有一行用于配置内核坏内存排除。因此,我假设这是映射显示错误的内存部分的首选方法。我设置的行是

GRUB_BADRAM="0x7DDF0000,0xffffc000" 

我发现每个网站都建议运行 memtest86 并让它显示 BadRAM 设置。memtest86 给了我一页我必须输入的内容。我可以看到所有地址都在一个 16K 块中,所以我只想将该 16K 块映射为无效。下面是我生成正确条目的方法。

第一个参数很简单。即坏内存的基地址。就我而言,我可以看到所有坏地址都大于 0x7DDF0000 且小于 0x7DDF4000。因此,我将 16K 块的开头作为起始地址。

第二个参数是掩码。在您想要的地址范围共享相同值的地方放置 1,在它会变化的地方放置 0。这意味着您需要选择地址范围,使得只有低位会变化。查看我的地址,掩码的第一部分很简单。您想从 0xffff 开始。对于下一个半字节,我将使用位图进行解释。我希望范围从 0000 到 0011。因此,badram 的掩码将是 1100 或十六进制 c。掩码中的最后 3 个半字节需要全部为 0,因为我们希望映射整个范围。因此,我们得到的总结果是 0xffffc000。

在 /etc/default/grub 中设置此行后,我运行了 sudo update-grub 并重新启动,我的坏内存不再被使用。使用此方法无需内核补丁即可映射坏内存。

dmesg您可以通过运行并查找BIOS-provided physical RAM map或来检查提供的范围是否正确extended physical RAM map

[    0.000000] BIOS-e820: [mem 0x000000022a898000-0x000000022a89bfff] unusable

您还可以/proc/iomem以 root 身份检查不可用的范围。


当然,最好的行动计划是更换有缺陷的 RAM。

答案2

我发现对我来说最简单、最有效的方法是添加核参数memtest=4到我的 GRUB 配置。这会增加几秒钟的启动时间,在此期间内核会检查您的 RAM,然后将其标记为对您不利。

  1. sudo nano /etc/default/grub

  2. 更新此行:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash memtest=4"
    
  3. sudo update-grub

  4. reboot

  5. 或者,通过运行检查它是否正常工作dmesg并查看如下日志:

    [    5.043917]   aaaaaaaaaaaaaaaa bad mem addr 0x0000000581a90000 - 0x0000000581a90010 reserved
    

来源

答案3

heynnema 的回答如果你有内核锁定已启用(如果您使用安全启动,则默认启用)。

AmanicA 的回答并不能真正扩展:它会在每次启动时运行测试,从而减慢您的启动时间。

您可以使用内核命令行参数memmap来保留某些物理内存区域,以免它们被使用。

内核参数了解详情。

例如,memtest86+ 和 linux memtest 发现我的机器上的地址 0x22a89a128 有故障。

因此我在内核命令行中添加了以下行,以禁用故障 RAM 页面周围的 8KiB RAM:

memmap=16K$0x22a898000

它保留(这就是 的用途$)从物理地址开始的 16 KiB 内存0x22a898000

我通过编辑并在该文件的变量末尾/etc/default/grub添加,然后运行来完成此操作。memmap=16K\\\$0x22a898000GRUB_CMDLINE_LINUX_DEFAULTsudo update-grub

\\\是因为 grub 进行了一些奇怪的字符转义。

您可以通过在 dmesg 中查找保留区域或以/proc/iomemroot 身份打开来验证这是否有效:

# grep 22a89 /proc/iomem
100000000 - 22a897fff : System RAM
22a898000 - 22a89bfff : Reserved
22a89c000 - 4807fffff : System RAM

答案4

为了跟进 @heynnema 的回答,我编写了一个小型 Python 脚本来计算掩码应该是什么。我不确定使用 bin 操作找到最左边有效 0 的位置的正确方法是什么,所以我用基于字符串的函数对其进行了破解。但它确实可以以编程方式找到掩码应该是什么:

def find_grub_badram_format(start, stop):
    """
    References:
        https://askubuntu.com/questions/908925/how-do-i-tell-ubuntu-not-to-use-certain-memory-addresses

    Example:
        start = 0x7DDF0000
        stop  = 0x7DDF4000 - 1
    """
    import numpy as np
    nbytes = 64
    dtype = np.uint64
    # Starting bad mem address range
    start = dtype(start)
    # Subtract 1 because to make the stop range inclusive instead of exclusive
    stop  = dtype(stop)

    def xnor(a, b):
        return ~(a ^ b)

    def find_pos_of_leftmost_sig_zero(a, nbytes=64):
        """
        Given a bit string like, we find the position of the first zero bit we
        see coming from the left, such that we can right-bitshift to it to the

            011111110110110
             ^      ^

        Example:
            >>> nbytes = 32
            >>> vals = [0b0, 0b1, 0b1111011, 0b1001]
            >>> for a in vals:
            >>>     print('-----')
            >>>     pos0 = find_pos_of_leftmost_sig_one_and_zero(a, nbytes)
            >>>     print(f'a = {a:032b}')
            >>>     print('    ' + ' ' * (nbytes - pos0 - 1) + '^')
            -----
            a = 00000000000000000000000000000000
                                               ^
            -----
            a = 00000000000000000000000000000001
                                               ^
            -----
            a = 00000000000000000000000001111011
                                             ^
            -----
            a = 00000000000000000000000000001001
                                             ^
        """
        # not really a fast op, but it works well enough There is a semi-corner
        # case at 1 and 0, but it doesnt change how we use it
        binstr = ('{:0' + str(nbytes) + 'b}').format(a)
        try:
            leftmost_one = binstr.index('1')
        except ValueError:
            return 0
        try:
            leftmost_sig_zero = binstr[leftmost_one:].index('0') + leftmost_one
        except Exception:
            return 0
        # Flip string indexes to bit indexes
        sig_zero = nbytes - (leftmost_sig_zero + 1)
        return sig_zero

    def find_first_sig_one(a, nbytes=64):
        binstr = ('{:0' + str(nbytes) + 'b}').format(a)
        leftmost_one = binstr.index('1')
        sig_one = nbytes - (leftmost_one + 1)
        return sig_one


    # Find all the bits in common
    common = xnor(start, stop)

    # Find the position of the first zero (non-common bit) we see from the left
    shift0 = find_pos_of_leftmost_sig_zero(common, nbytes) + 1

    # Find the number of significant bits in the stop position
    shift1 = find_first_sig_one(stop, nbytes) + 1


    shift0 = dtype(shift0)
    shift1 = dtype(shift1)

    head_mask = (dtype(1) << shift1) - dtype(1)
    tail_mask = ~((dtype(1) << shift0) - dtype(1))
    mask = head_mask & tail_mask

    print(f'start  = 0b{start:064b} = 0x{start:016x}')
    print(f'stop   = 0b{stop:064b} = 0x{stop:016x}')
    print(f'common = 0b{common:064b} = 0x{common:016x}')
    print(f'mask   = 0b{mask:064b} = 0x{mask:016x}')

    print('--')
    print(f'mask = ' + hex(mask))

    badram_format = f'{start:#0{18}x},{mask:#0{18}x}'
    print(badram_format)
    badram_format = f'{start:#x},{mask:#x}'
    print(badram_format)

这导致

start  = 0b0000000000000000000000000000000001111101110111110000000000000000 = 0x000000007ddf0000
stop   = 0b0000000000000000000000000000000001111101110111110011111111111111 = 0x000000007ddf3fff
common = 0b1111111111111111111111111111111111111111111111111100000000000000 = 0xffffffffffffc000
mask   = 0b0000000000000000000000000000000001111111111111111100000000000000 = 0x000000007fffc000
--
mask = 0x7fffc000
0x000000007ddf0000,0x000000007fffc000
0x7ddf0000,0x7fffc000

相关内容