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  */
===============================================================================
