Linux Kernel 2.6 Documentation:
/usr/src/linux/Documentation/mtrr.txt
mtrr.txt
パフォーマンスを上げるために PPro Memory Type Range Register を用いる方法
[プレインテキスト版]
- 原著作者: Richard Gooch <rgooch@atnf.csiro.au>
- 翻訳者: 野本浩一 <hng@ps.ksky.ne.jp>
- バージョン: 2.6.0
- 翻訳日時: 2001/10/25
MTRR (Memory Type Range Register) の制御
3 Jun 1999
著者:Richard Gooch <rgooch@atnf.csiro.au>
日本語訳:Hiroshi Kajisha <hkajisha@din.or.jp>
野本浩一 <hng@ps.ksky.ne.jp>
校正:武井伸光さん <takei@kondara.org>
山下義之さん <dica@eurus.dti.ne.jp>
森本淳さん <morimoto@xantia.citroen.org>
Intel の P6 ファミリプロセッサ (Pentium Pro, Pentium II およびそれ以
降) 上の Memory Type Range Registers (MTTRs) はプロセッサがメモリへ
アクセスする範囲を制御するために使うことが可能です。PCI あるいは AGP
バス上のビデオ (VGA) カードを使っている場合、とても有用です。
write-combining を有効にすると、PCI/AGP バスを占有する前に、バスへの
書き込み転送を大きな転送へ連結することが行われます。これは画像の書き
込み動作のパフォーマンスを 2.5 倍以上向上します。
Cyrix の 6x86, 6x86MX, M II プロセッサには MTRR と同様の機能を持つ
Address Range Registers (ARRs) があります。これらのプロセッサでは、
MTRR をエミュレートするために、ARR が使用されます。
AMD の K6-2(stepping 8 以上) および K6-3 プロセッサには MTRR が二つ
あります。これらはサポートされます。AMD の Athlon ファミリには Intel
スタイルな MTRR が八つあります。
Centaur C6 (WinChip) は write-combining 可能な八つの MCR があります。
これらはサポートされます。
VIA の Cyrix III および C3 CPU には Intel スタイルな MTRR が八つあり
ます。
CONFIG_MTRR オプションは、MTRR を操作できるようにするためのファイル
/proc/mtrr を作成します。通常、X サーバは MTRR を使用するはずです。
これは合理的で一般的なインターフェースのはずなので、他のプロセッサの
同様な制御レジスタも容易にサポートできるしょう。
/proc/mtrr のインターフェースは二つあります - 一つは人が読み書きできる
ASCII インターフェースです。もう一つは ioctl() インターフェースです。
ASCII インターフェースは MTRR の管理用のものです。ioctl() インターフェー
スは C プログラム (言い換えれば X サーバ) 用のものです。二つのインター
フェースを以下でコマンドおよび C のコードを用い、説明します。
===============================================================================
シェルから MTRR を読む -
% cat /proc/mtrr
reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1
reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1
===============================================================================
C シェルから MTRR を作る -
# echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr
あるいは、bash を使うなら -
# echo "base=0xf8000000 size=0x400000 type=write-combining" >| /proc/mtrr
そして、その結果は
% cat /proc/mtrr
reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1
reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1
reg02: base=0xf8000000 (3968MB), size= 4MB: write-combining, count=1
これは、ベースアドレスが 0xf8000000 でサイズが 4 メガバイトのビデオ
RAM のものです。ベースアドレスを調べるには、リニアフレームバッファの
アドレスが示してある X サーバの出力を見る必要があります。通常次のよう
な行があります -
(--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000
X サーバからの値だけを使用するべきで、X サーバはフレームバッファのベー
スアドレスを動かすので、X サーバより報告される値だけが信頼できるという
ことに注意してください。
フレームバッファのサイズを調べるには (えっ、本当に知らないの?)、次の
行が示しています -
(--) S3: videoram: 4096k
4 メガバイト (16進数では 0x400000 バイト) です。MTRR の設定を自動で行
う XFree86 用のパッチは作成中です - 言い換えれば、X サーバは ioctl()
インターフェースを使用して /proc/mtrr を扱うようになるので、ユーザは何
もする必要がなくなります。商用 X サーバを使うなら、ベンダに MTRR のサ
ポートを追加するよう頼んでください。
===============================================================================
重なり合う MTRR を作る -
%echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr
%echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr
そして、cat /proc/mtrr として結果を見ると -
reg00: base=0x00000000 ( 0MB), size= 64MB: write-back, count=1
reg01: base=0xfb000000 (4016MB), size= 16MB: write-combining, count=1
reg02: base=0xfb000000 (4016MB), size= 4kB: uncachable, count=1
いくつかのカード (特に Voodoo グラフィックボード) は、レジスタが使用す
る 4 kb の領域を、ビデオ RAM の先頭から除外することが必要です。
注意:はじめに作った領域が type=write-combining の場合、
type=uncachable のみ作ることができます。
===============================================================================
C シェルから MTRR を削除 -
% echo "disable=2" >! /proc/mtrr
あるいは bash を使用して -
% echo "disable=2" >| /proc/mtrr
[訳注;この 2 は cat /proc/mtrr で見た reg ナンバーです。]
===============================================================================
ioctl() を使用して C プログラムから MTRR を読む -
[訳注;usage は mtrr-show です。]
/* mtrr-show.c
Source file for mtrr-show (example programme to show MTRRs using ioctl()'s)
Copyright (C) 1997-1998 Richard Gooch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Richard Gooch may be reached by email at rgooch@atnf.csiro.au
The postal address is:
Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
*/
/*
This programme will use an ioctl() on /proc/mtrr to show the current MTRR
settings. This is an alternative to reading /proc/mtrr.
Written by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 2-MAY-1998
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
int main ()
{
int fd;
struct mtrr_gentry gentry;
if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) == -1 )
{
if (errno == ENOENT)
{
fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
stderr);
exit (1);
}
fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
exit (2);
}
for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
++gentry.regnum)
{
if (gentry.size < 1)
{
fprintf (stderr, "Register: %u disabled\n", gentry.regnum);
continue;
}
fprintf (stderr, "Register: %u base: 0x%lx size: 0x%lx type: %s\n",
gentry.regnum, gentry.base, gentry.size,
mtrr_strings[gentry.type]);
}
if (errno == EINVAL) exit (0);
fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
exit (3);
} /* End Function main */
===============================================================================
ioctl() を使用して C プログラムから MTRR を作る -
[訳注;このコードの ioctl() の引数について、MTRRIOC_ADD_ENTRY ではプロ
グラムは正常終了しますが何も起こりません。MTRRIOC_SET_ENTRY で追加され
ます。このことは著者に連絡済みです。
usage はコードのとおり mtrr-add base size type で、base, size ともに
0x を接頭につけても動き、type は include/asm/mtrr.h 内の
static char *mtrr_strings[MTRR_NUM_TYPES] で定義された文字列で引用符を
付けずに指定します。]
/* mtrr-add.c
Source file for mtrr-add (example programme to add an MTRRs using ioctl())
Copyright (C) 1997-1998 Richard Gooch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Richard Gooch may be reached by email at rgooch@atnf.csiro.au
The postal address is:
Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
*/
/*
This programme will use an ioctl() on /proc/mtrr to add an entry. The first
available mtrr is used. This is an alternative to writing /proc/mtrr.
Written by Richard Gooch 17-DEC-1997
Last updated by Richard Gooch 2-MAY-1998
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#define MTRR_NEED_STRINGS
#include <asm/mtrr.h>
#define TRUE 1
#define FALSE 0
#define ERRSTRING strerror (errno)
int main (int argc, char **argv)
{
int fd;
struct mtrr_sentry sentry;
if (argc != 4)
{
fprintf (stderr, "Usage:\tmtrr-add base size type\n");
exit (1);
}
sentry.base = strtoul (argv[1], NULL, 0);
sentry.size = strtoul (argv[2], NULL, 0);
for (sentry.type = 0; sentry.type < MTRR_NUM_TYPES; ++sentry.type)
{
if (strcmp (argv[3], mtrr_strings[sentry.type]) == 0) break;
}
if (sentry.type >= MTRR_NUM_TYPES)
{
fprintf (stderr, "Illegal type: \"%s\"\n", argv[3]);
exit (2);
}
if ( ( fd = open ("/proc/mtrr", O_WRONLY, 0) ) == -1 )
{
if (errno == ENOENT)
{
fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
stderr);
exit (3);
}
fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
exit (4);
}
if (ioctl (fd, MTRRIOC_ADD_ENTRY, &sentry) == -1)
{
fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
exit (5);
}
fprintf (stderr, "Sleeping for 5 seconds so you can see the new entry\n");
sleep (5);
close (fd);
fputs ("I've just closed /proc/mtrr so now the new entry should be gone\n",
stderr);
} /* End Function main */
===============================================================================
Linux カーネル 2.6 付属文書一覧へ戻る