[内核文档]MTRR (Memory Type Range Register) 控制

MTRR (Memory Type Range Register) control

 

         Intel P6系列的处理器上(Pentium Pro, Pentium II and later),内存类型范围寄存器(MTRRs)可以控制处理器对内存区域的访问。 如果系统中存在基于PCIAGP总线的视频卡(VGA),MTRR将具有非常显著的作用。通过使能写捆绑(Write-combining),可以在总线传输开始前,将若干个总线写传输捆绑成一次较大的写传输操作。这可以将图像写操作的性能提高2.5倍或者更多。

         Cyrix 6x86, 6x86MX 以及 M II处理器具有地址范围寄存器(ARRsAddress Range Registers),ARRs可以提供与MTRR类似的功能,能够用来模拟MTRRs

         AMD K6-2stepping 8及以上)与K6-3处理器拥有2MTRRAMD Athlon系列的处理器拥有8个与Intel类似的MTRRs

         Centaur C6WinChip)拥有8MCRs,运行写捆绑(WC)。

         VIA Cyrix III 以及 VIA C3 CPU能够提供8个类似于Intel的处理器。

         选中配置选项CONFIG_MTRR后,内核将创建文件/proc/mtrr,通过此文件,能够对MTRR进行操作。X server通常就是这样做的。当然了,今后会有更加通用的接口,因而其它处理器上类似的控制寄存器也能够被轻易的支持。

         文件/proc/mtrr具有2个接口:一个是ASCII接口,此接口可读可写。ASCII接口适用于管理。另一个是ioctl()接口,该接口适用于C程序(如,X Server)。下面我们将通过一些命令与C代码,详细地介绍这些接口。

Shell中读取MTRRs

 

% cat /proc/mtrr

reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1

reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1

利用C-shell创建MTRRs

# 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

新增加的区域就是Video RAM,基地址为0xf8000000,大小为4MB。在X Server的输出信息中,可以找到基地址,即线性缓存地址(linear framebuffer address)。包含基地址的输出信息可能如下:

(--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000

注意:X Server可能会修改framebuffer的基地址,因此只有X Server报告出的地址是可信的。

包含FrameBuffer大小的输出信息可能如下:

(--) S3: videoram:  4096k

此处为4MB,即0x400000字节。

一个XFree86的补丁可以自动地实现上述操作:也就是说X Server将通过ioctl()接口操作/proc/mtrr文件,用户不再需要自己处理了。如果使用商业的X Server,可以请生产商提供对MTRR的支持。

创建重叠的MTRRs

%echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr

%echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr

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图形卡)在Framebuffer区域之前需要4KB的空间,用来映射寄存器。

注意:如果创建的第一个区域是type=write-combining的,就可以只创建type=uncachable的区域。

C-shell中移除MTRRs:

% echo "disable=2" >! /proc/mtrr

或者使用bash:

% echo "disable=2" >| /proc/mtrr

C程序中使用ioctl()读取MTRRs

/*  mtrr-show.c

 

    Source file for mtrr-show (example program 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 program 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 <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/ioctl.h>

#include <errno.h>

#include <asm/mtrr.h>

 

#define TRUE 1

#define FALSE 0

#define ERRSTRING strerror (errno)

 

static char *mtrr_strings[MTRR_NUM_TYPES] =

{

    "uncachable",               /* 0 */

    "write-combining",          /* 1 */

    "?",                        /* 2 */

    "?",                        /* 3 */

    "write-through",            /* 4 */

    "write-protect",            /* 5 */

    "write-back",               /* 6 */

};

 

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

C程序中利用ioctl()创建MTRRs

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

#include <asm/mtrr.h>

 

#define TRUE 1

#define FALSE 0

#define ERRSTRING strerror (errno)

 

static char *mtrr_strings[MTRR_NUM_TYPES] =

{

    "uncachable",               /* 0 */

    "write-combining",          /* 1 */

    "?",                        /* 2 */

    "?",                        /* 3 */

    "write-through",            /* 4 */

    "write-protect",            /* 5 */

    "write-back",               /* 6 */

};

 

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

 

阅读更多

没有更多推荐了,返回首页