Monday, September 26, 2011

Bad Memory

我的舊台機最近跑emerge的時候只要遇到compile很久的包(e.g. www-client/chromium)就會出現随機的segmentation fault或internal compiler error。因為每次出錯地方都不同,很明顯是舊電腦的硬體問題。检查硬碟後發現正常。跑memtest發現有一根RAM壞了。内存地址0x1AE501B80x1AFD3FE3出現錯誤。嗯,Gentoo真的可能比較傷硬體。

發現了問題就好解决。把壞掉的RAM拔掉(四根RAM唯一一根generic brand的。這教訓我硬體還是買名牌的好)。但這樣我就少了1GB了。買新的?這電腦舊到不想再化錢了。(我很吝啬)。Google一下發現GRUB2原來有很強的功能:

badram addr,mask[,addr,mask...]
只要那OS的kernel由GRUB2手上拿取memory map,GRUB可以告訴启動的OS不要用某段内存。(像Windows這用chainload的OS應該不行吧?)badram接受和memtest的address/mask一樣的參數對。address是第一個内存地址。mask的定義是1指固定數位、0指可改變數位。


但是壞掉RAM的間隔很复雜,不是一組參數就可以specify的。所以必須分段解决。第一段比較容易:0x1AE501B8-0x1AEFFFFF。保持前3位不變的mask是0xFFF00000。從0x1AF00000開始就比較麻煩了。因為從0x0-0xD每個數位都變化。用簡單的mask那將會把一些正常的内存地址也包含在badram裡。所以要把這段間隔分成更小的間隔。例如用0x1AF00000,0xFFF80000可以加入0x1AF00000-0x1AF7FFFF。如此類推……

這麼麻煩的計算當然要交給電腦:

#!/usr/bin/evn python

addr1 = 0x1AE501B8
addr2 = 0x1AFD3FE3
BASE = 0x100000000

def findmask(a0, a1, pcount = 1):
	if a0 > a1:
		raise ValueError ("Second argument must be greater than or equal to the first argument")

	msk = 0xFFFFFFFF
	oldmsk, oldsum = msk, a0
	while True:
		D = (( a0 | ~msk ) % BASE)
		if D <= a1:
			oldsum = D
			oldmsk = msk
		if D >= a1:
			break
		msk = ( msk << 1 ) % BASE

	print "%2d: 0x%X, 0x%X, 0x%X" % (pcount, a0, oldmsk, oldsum)
	if oldsum == a1:
		return oldmsk, oldsum
	else:
		return findmask(oldsum+1, a1, pcount + 1)

findmask(addr1, addr2)
出來的結果:
addressmaskRANGE
0x1AE501B80xFFF000000x1AEFFFFF
0x1AF000000xFFF800000x1AF7FFFF
0x1AF800000xFFFC00000x1AFBFFFF
0x1AFC00000xFFFF00000x1AFCFFFF
0x1AFD00000xFFFFE0000x1AFD1FFF
0x1AFD20000xFFFFF0000x1AFD2FFF
0x1AFD30000xFFFFF8000x1AFD37FF
0x1AFD38000xFFFFFC000x1AFD3BFF
0x1AFD3C000xFFFFFE000x1AFD3DFF
0x1AFD3E000xFFFFFF000x1AFD3EFF
0x1AFD3F000xFFFFFF800x1AFD3F7F
0x1AFD3F800xFFFFFFC00x1AFD3FBF
0x1AFD3FC00xFFFFFFE00x1AFD3FDF
0x1AFD3FE00xFFFFFFFC0x1AFD3FE3
共14組參數!

最後修正設定和重跑
$ echo 'GRUB_BADRAM = "0x1AE501B8,0xFFF00000,0x1AF00000,0xFFF80000,..."' >> /etc/default/grub
$ grub2-mkconfig -o /boot/grub2/grub.cfg
就可以了。把壞掉的内存地址排除掉後memtest没有找到新的錯誤。www-client/chromium正在快樂compile中……

No comments: