# 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"
为了继续@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)
如果您查看
/etc/default/grub
,您会发现一个GRUB_BADRAM=
参数,您可以在其中识别哪些坏内存位置存在。设置好地址后,运行
sudo update-grub
应用。注意:这
GRUB_BADRAM
不适用于内核锁定(如果您有安全启动,则会启用)。您可以通过运行检查是否启用了安全启动mokutil --sb-state
。取自https://help.ubuntu.com/community/BadRAM#BADRAM_setting_in_Grub2 ...
Grub2 中的 BADRAM 设置
Natty 中的 GRUB2 配置文件有一行用于配置内核坏 ram 排除项。因此,我将假设这是映射出显示错误的内存部分的首选方法。我设置的线是
在我能找到的每个网站上,建议的方法是运行 memtest86 并让它显示 BadRAM 设置。memtest86 给了我一页我必须输入的东西。我可以看到所有地址都在一个 16K 块中,所以我只想映射那个 16K 块停止运行。这是我生成正确条目的方式。
第一个参数很简单。那是坏内存的基地址。就我而言,我可以看到所有坏地址都大于 0x7DDF0000 且小于 0x7DDF4000。所以,我把 16K 块的开头作为我的起始地址。
第二个参数是掩码。您将 1s 放在您想要的地址范围共享相同值的位置,并将 0s 放在它会变化的位置。这意味着您需要选择您的地址范围,以便只有低位发生变化。看我的地址,面具的第一部分很容易。你想从 0xffff 开始。对于下一个半字节,我将使用位图进行解释。我希望范围从 0000 到 0011。因此,badram 的掩码将是 1100 或十六进制 c。掩码中的最后 3 个半字节需要全为 0,因为我们想要映射出整个范围。所以,我们得到的总结果是 0xffffc000。
在 /etc/default/grub 中设置此行后,我运行 sudo update-grub 并重新启动,我的坏内存不再被使用。使用这种方法不需要内核补丁来映射坏内存。
dmesg
您可以通过运行并查找BIOS-provided physical RAM map
or来检查提供的范围是否正确extended physical RAM map
:您还可以
/proc/iomem
以 root 身份检查以查看不可用的范围。当然,最好的行动计划是更换有缺陷的 RAM。
我发现对我来说最简单、最可靠的方法是将内核参数
memtest=4
添加到我的 GRUB 配置中。这会增加几秒钟的启动时间,内核会检查您的 ram,然后将它们标记为对您不利。sudo nano /etc/default/grub
更新这一行:
sudo update-grub
reboot
或者,通过运行检查它是否正常工作
dmesg
并查看如下日志:来源。
为了继续@heynnema 的回答,我编写了一个小的 python 脚本来计算掩码应该是什么。我不确定使用 bin 操作找到最左边的 0 位置的正确方法是什么,所以我使用基于字符串的函数对其进行了破解。但它确实适用于以编程方式查找掩码:
这导致
如果您启用了内核锁定(如果您使用安全启动,则默认情况下启用), heynnema 的答案不起作用。
AmanicA 的回答并没有真正扩展:它会在每次启动时运行测试,从而减慢您的启动时间。
您可以使用内核 cmdline 参数
memmap
来保留某些物理内存区域,以便不使用它们。有关详细信息,请参阅内核参数。
例如,memtest86+ 和 linux memtest 发现地址 0x22a89a128 在我的机器上出现故障。
因此,我在内核 cmdline 中添加了以下行,以禁用故障内存页面周围的 8KiB 内存:
memmap=16K$0x22a898000
从物理地址开始保留(这就是
$
它的用途)16 KiB 的内存0x22a898000
。我通过在该文件中的变量末尾进行编辑
/etc/default/grub
和添加,然后运行.memmap=16K\\\$0x22a898000
GRUB_CMDLINE_LINUX_DEFAULT
sudo update-grub
这
\\\
是因为 grub 做了一些奇怪的字符转义。您可以通过在 dmesg 中查找保留区域或以
/proc/iomem
root 身份打开来验证这是否有效: