Thinkpad X61 4G内存Mtrr表错误

作者:forever steel

X61加到4G内存之后, Linux下面发现显卡速度比较慢, 性能明显下降. 最明显的是用wine运行星际争霸或者魔兽争霸的时候, 鼠标反应非常慢.

用dmesg命令可以看到

mtrr: type mismatch for e0000000,10000000
old: write-back new: write-combining

在/var/log/Xorg.0.log中也看到有同样的字样.

查看一下/proc/mtrr

reg00: base=0xc0000000 (3072MB), size=1024MB: uncachable, count=1
reg01: base=0x13c000000 (5056MB), size=  64MB: uncachable, count=1
reg02: base=0x00000000 (   0MB), size=4096MB: write-back, count=1
reg03: base=0x100000000 (4096MB), size=1024MB: write-back, count=1
reg04: base=0xbf700000 (3063MB), size=   1MB: uncachable, count=1
reg05: base=0xbf800000 (3064MB), size=   8MB: uncachable, count=1

其中在运行X的时候, 显卡需要在mtrr表中注册e0000000,10000000(256M大小)这段地址为write-combining, 这种模式会提升显卡速度2.5倍.但是这段地址已经被注册为write-back模式, 所以造成这个问题.

关于这个bug, 见: https://bugs.launchpad.net/linux/+bug/210780

这个页面提供了一个脚本(http://launchpadlibrarian.net/13330029/fix-mtrrs.sh), 解决这个问题.

我把脚本改了一下, 符合我的机器的设置, 但是还有一个问题, Mtrr表最多支持8个记录, 我只好删掉一个overlap的项(不知道是否有更好的办法, 反正还没有出现别的问题), 来支持这段内存地址为write-combining模式. 运行fix脚本之后的mtrr:

reg00: base=0xc0000000 (3072MB), size= 512MB: uncachable, count=1
reg01: base=0x13c000000 (5056MB), size=  64MB: uncachable, count=1
reg02: base=0x00000000 (   0MB), size=2048MB: write-back, count=1
reg03: base=0x100000000 (4096MB), size=1024MB: write-back, count=1
reg04: base=0xf0000000 (3840MB), size= 256MB: uncachable, count=1
reg05: base=0xbf800000 (3064MB), size=   8MB: uncachable, count=1
reg06: base=0x80000000 (2048MB), size=1024MB: write-back, count=1
reg07: base=0xe0000000 (3584MB), size= 256MB: write-combining, count=1

修改后的脚本rc.mtrr(放在/etc/rc.d目录下, 在rc.local里面执行)如下:

#!/bin/bash

MTRR=/proc/mtrr

echo "disable=2" > $MTRR
echo "base=0x00000000 size=0x80000000 type=write-back" > $MTRR
echo "base=0x80000000 size=0x40000000 type=write-back" > $MTRR

echo "disable=0" > $MTRR
echo "disable=4" > $MTRR
echo "base=0xc0000000 size=0x20000000 type=uncachable" > $MTRR
#echo "base=0xe0000000 size=0x10000000 type=write-combining" > $MTRR
echo "base=0xf0000000 size=0x10000000 type=uncachable" > $MTRR

其中最后注释的一行就是显卡需要的一段地址, 因为X启动的时候会自动注册, 所以只要留出来这段就行了, 这行代码可以注释掉.