如果措辞不当,我很抱歉,但我在我的一台电脑上做过内存测试,某些内存地址有错误。这是我第一次搜索。如果你需要更多信息,我可以提供。
答案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,然后将其标记为对您不利。
sudo nano /etc/default/grub
更新此行:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash memtest=4"
sudo update-grub
reboot
或者,通过运行检查它是否正常工作
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\\\$0x22a898000
GRUB_CMDLINE_LINUX_DEFAULT
sudo update-grub
这\\\
是因为 grub 进行了一些奇怪的字符转义。
您可以通过在 dmesg 中查找保留区域或以/proc/iomem
root 身份打开来验证这是否有效:
# 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