1MTRR (Memory Type Range Register) control 22 May 1998 3Richard Gooch 4<rgooch@atnf.csiro.au> 5 6 On Intel Pentium Pro/Pentium II systems the Memory Type Range 7 Registers (MTRRs) may be used to control processor access to memory 8 ranges. This is most useful when you have a video (VGA) card on a 9 PCI or AGP bus. Enabling write-combining allows bus write transfers 10 to be combined into a larger transfer before bursting over the 11 PCI/AGP bus. This can increase performance of image write operations 12 2.5 times or more. 13 14 The CONFIG_MTRR option creates a /proc/mtrr file which may be used 15 to manipulate your MTRRs. Typically the X server should use 16 this. This should have a reasonably generic interface so that 17 similar control registers on other processors can be easily 18 supported. 19 20 21There are two interfaces to /proc/mtrr: one is an ASCII interface 22which allows you to read and write. The other is an ioctl() 23interface. The ASCII interface is meant for administration. The 24ioctl() interface is meant for C programmes (i.e. the X server). The 25interfaces are described below, with sample commands and C code. 26 27=============================================================================== 28Reading MTRRs from the shell: 29 30% cat /proc/mtrr 31reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1 32reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1 33=============================================================================== 34Creating MTRRs from the shell: 35# echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr 36 37And the result thereof: 38% cat /proc/mtrr 39reg00: base=0x00000000 ( 0MB), size= 128MB: write-back, count=1 40reg01: base=0x08000000 ( 128MB), size= 64MB: write-back, count=1 41reg02: base=0xf8000000 (3968MB), size= 4MB: write-combining, count=1 42 43This is for video RAM at base address 0xf8000000 and size 4 megabytes. To 44find out your base address, you need to look at the output of your X 45server, which tells you where the linear framebuffer address is. A 46typical line that you may get is: 47 48(--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000 49 50Note that you should only use the value from the X server, as it may 51move the framebuffer base address, so the only value you can trust is 52that reported by the X server. 53 54To find out the size of your framebuffer (what, you don't actually 55know?), the following line will tell you: 56 57(--) S3: videoram: 4096k 58 59That's 4 megabytes, which is 0x400000 bytes (in hexadecimal). 60A patch is being written for XFree86 which will make this automatic: 61in other words the X server will manipulate /proc/mtrr using the 62ioctl() interface, so users won't have to do anything. If you use a 63commercial X server, lobby your vendor to add support for MTRRs. 64=============================================================================== 65Creating overlapping MTRRs: 66 67%echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr 68%echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr 69 70And the results: cat /proc/mtrr 71reg00: base=0x00000000 ( 0MB), size= 64MB: write-back, count=1 72reg01: base=0xfb000000 (4016MB), size= 16MB: write-combining, count=1 73reg02: base=0xfb000000 (4016MB), size= 4kB: uncachable, count=1 74 75Some cards (especially Voodoo Graphics boards) need this 4 kB area 76excluded from the beginning of the region because it is used for 77registers. 78 79NOTE: You can only create type=uncachable region, if the first 80region that you created is type=write-combining. 81=============================================================================== 82Removing MTRRs from the shell: 83% echo "disable=2" >! /proc/mtrr 84=============================================================================== 85Reading MTRRs from a C programme using ioctl()'s: 86 87/* mtrr-show.c 88 89 Source file for mtrr-show (example programme to show MTRRs using ioctl()'s) 90 91 Copyright (C) 1997-1998 Richard Gooch 92 93 This program is free software; you can redistribute it and/or modify 94 it under the terms of the GNU General Public License as published by 95 the Free Software Foundation; either version 2 of the License, or 96 (at your option) any later version. 97 98 This program is distributed in the hope that it will be useful, 99 but WITHOUT ANY WARRANTY; without even the implied warranty of 100 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 101 GNU General Public License for more details. 102 103 You should have received a copy of the GNU General Public License 104 along with this program; if not, write to the Free Software 105 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 106 107 Richard Gooch may be reached by email at rgooch@atnf.csiro.au 108 The postal address is: 109 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. 110*/ 111 112/* 113 This programme will use an ioctl() on /proc/mtrr to show the current MTRR 114 settings. This is an alternative to reading /proc/mtrr. 115 116 117 Written by Richard Gooch 17-DEC-1997 118 119 Last updated by Richard Gooch 2-MAY-1998 120 121 122*/ 123#include <stdio.h> 124#include <string.h> 125#include <sys/types.h> 126#include <sys/stat.h> 127#include <fcntl.h> 128#include <sys/ioctl.h> 129#include <errno.h> 130#define MTRR_NEED_STRINGS 131#include <asm/mtrr.h> 132 133#define TRUE 1 134#define FALSE 0 135#define ERRSTRING strerror (errno) 136 137 138int main () 139{ 140 int fd; 141 struct mtrr_gentry gentry; 142 143 if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) == -1 ) 144 { 145 if (errno == ENOENT) 146 { 147 fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n", 148 stderr); 149 exit (1); 150 } 151 fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING); 152 exit (2); 153 } 154 for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0; 155 ++gentry.regnum) 156 { 157 if (gentry.size < 1) 158 { 159 fprintf (stderr, "Register: %u disabled\n", gentry.regnum); 160 continue; 161 } 162 fprintf (stderr, "Register: %u base: 0x%lx size: 0x%lx type: %s\n", 163 gentry.regnum, gentry.base, gentry.size, 164 mtrr_strings[gentry.type]); 165 } 166 if (errno == EINVAL) exit (0); 167 fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING); 168 exit (3); 169} /* End Function main */ 170=============================================================================== 171Creating MTRRs from a C programme using ioctl()'s: 172 173/* mtrr-add.c 174 175 Source file for mtrr-add (example programme to add an MTRRs using ioctl()) 176 177 Copyright (C) 1997-1998 Richard Gooch 178 179 This program is free software; you can redistribute it and/or modify 180 it under the terms of the GNU General Public License as published by 181 the Free Software Foundation; either version 2 of the License, or 182 (at your option) any later version. 183 184 This program is distributed in the hope that it will be useful, 185 but WITHOUT ANY WARRANTY; without even the implied warranty of 186 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 187 GNU General Public License for more details. 188 189 You should have received a copy of the GNU General Public License 190 along with this program; if not, write to the Free Software 191 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 192 193 Richard Gooch may be reached by email at rgooch@atnf.csiro.au 194 The postal address is: 195 Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. 196*/ 197 198/* 199 This programme will use an ioctl() on /proc/mtrr to add an entry. The first 200 available mtrr is used. This is an alternative to writing /proc/mtrr. 201 202 203 Written by Richard Gooch 17-DEC-1997 204 205 Last updated by Richard Gooch 2-MAY-1998 206 207 208*/ 209#include <stdio.h> 210#include <string.h> 211#include <stdlib.h> 212#include <unistd.h> 213#include <sys/types.h> 214#include <sys/stat.h> 215#include <fcntl.h> 216#include <sys/ioctl.h> 217#include <errno.h> 218#define MTRR_NEED_STRINGS 219#include <asm/mtrr.h> 220 221#define TRUE 1 222#define FALSE 0 223#define ERRSTRING strerror (errno) 224 225 226int main (int argc, char **argv) 227{ 228 int fd; 229 struct mtrr_sentry sentry; 230 231 if (argc != 4) 232 { 233 fprintf (stderr, "Usage:\tmtrr-add base size type\n"); 234 exit (1); 235 } 236 sentry.base = strtoul (argv[1], NULL, 0); 237 sentry.size = strtoul (argv[2], NULL, 0); 238 for (sentry.type = 0; sentry.type < MTRR_NUM_TYPES; ++sentry.type) 239 { 240 if (strcmp (argv[3], mtrr_strings[sentry.type]) == 0) break; 241 } 242 if (sentry.type >= MTRR_NUM_TYPES) 243 { 244 fprintf (stderr, "Illegal type: \"%s\"\n", argv[3]); 245 exit (2); 246 } 247 if ( ( fd = open ("/proc/mtrr", O_WRONLY, 0) ) == -1 ) 248 { 249 if (errno == ENOENT) 250 { 251 fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n", 252 stderr); 253 exit (3); 254 } 255 fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING); 256 exit (4); 257 } 258 if (ioctl (fd, MTRRIOC_ADD_ENTRY, &sentry) == -1) 259 { 260 fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING); 261 exit (5); 262 } 263 fprintf (stderr, "Sleeping for 5 seconds so you can see the new entry\n"); 264 sleep (5); 265 close (fd); 266 fputs ("I've just closed /proc/mtrr so now the new entry should be gone\n", 267 stderr); 268} /* End Function main */ 269=============================================================================== 270

