Re: Linux 2.0.36pre8 (release candidate one aka 'no chance')

Henning P. Schmiedehausen (hps@tanstaafl.de)
7 Sep 1998 22:01:40 +0200


alan@lxorguk.ukuu.org.uk (Alan Cox) writes:

>Is now on ftp://ftp.linux.org.uk/pub/linux/alan/...

>The preliminary 2.0.36 release notes are included below and maintained
>as http://roadrunner.swansea.linux.org.uk/relnotes.36.html

[...]

You left out the MTRR patch I sent to you. Was this intentional or did
it just get dropped from your mailbox?

I attached it here one more time; this fix made the Gigabyte GA-686DX
Dual PII board boot, without it, the Kernel will crash.

Kind regards
Henning

--- cut ---
diff -u --recursive --new-file linux-2.0.33/arch/i386/config.in linux-2.0.33-MTRR/arch/i386/config.in
--- linux-2.0.33/arch/i386/config.in Mon May 13 06:17:23 1996
+++ linux-2.0.33-MTRR/arch/i386/config.in Mon Feb 9 21:19:00 1998
@@ -43,6 +43,12 @@
486 CONFIG_M486 \
Pentium CONFIG_M586 \
PPro CONFIG_M686" Pentium
+
+# Conditionally compile MTRR manipulation support
+if [ "$CONFIG_M686" = "y" -o "$CONFIG_M586" = "y" ]; then
+ bool ' Fix broken SMP BIOS (for example GA-686DX)' CONFIG_MTRR
+fi
+
endmenu

source drivers/block/Config.in
diff -u --recursive --new-file linux-2.0.33/arch/i386/kernel/Makefile linux-2.0.33-MTRR/arch/i386/kernel/Makefile
--- linux-2.0.33/arch/i386/kernel/Makefile Tue Sep 16 23:33:59 1997
+++ linux-2.0.33-MTRR/arch/i386/kernel/Makefile Mon Feb 9 21:18:20 1998
@@ -26,6 +26,10 @@

ifdef SMP

+ifdef CONFIG_MTRR
+O_OBJS += mtrr.o
+endif
+
O_OBJS += smp.o

head.o: head.S $(TOPDIR)/include/linux/tasks.h
diff -u --recursive --new-file linux-2.0.33/arch/i386/kernel/mtrr.c linux-2.0.33-MTRR/arch/i386/kernel/mtrr.c
--- linux-2.0.33/arch/i386/kernel/mtrr.c Thu Jan 1 01:00:00 1970
+++ linux-2.0.33-MTRR/arch/i386/kernel/mtrr.c Mon Feb 9 21:18:20 1998
@@ -0,0 +1,602 @@
+/*
+ * Read and write Memory Type Range Registers (MTRRs)
+ *
+ * These machine specific registers contain information about
+ * caching of memory regions on Intel processors.
+ *
+ * This code has been derived from pform_mod.c by M. Tisch"auser
+ * (email martin@ikcbarka.fzk.de). Special thanks to mingo for
+ * his hint.
+ *
+ * (c) 1997 M. Ohlenroth <moh@informatik.tu-chemnitz.de>
+ * NO WARRANTY: use this code at your own risk!
+ *
+ * This code is released under the GNU public license version 2 or
+ * later.
+ *
+ * modified to have a /proc/mtrr interface by M. Fr"ohlich, Jan. 1998
+ * <frohlich@na.uni-tuebingen.de>
+ * the user Interface is partly taken form mtrr-patch-v1.5
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mtrr.h>
+
+#define MTRR_CAP 0x0fe /* MTRRcap register */
+#define MTRR_VARIABLE 0x200 /* variable length registers */
+#define MTRR_FIXED64K 0x250 /* fixed size registers 64k */
+#define MTRR_FIXED16K 0x258 /* fixed size registers 16K */
+#define MTRR_FIXED4K 0x268 /* fixed size registers 4K */
+#define MTRR_DEFTYPE 0x2ff /* MTRRdefType register */
+
+/*
+ * data type for the MTRRcap register
+ */
+typedef struct {
+ __u64 VCNT : 8 __attribute__ ((packed)),
+ FIX : 1 __attribute__ ((packed)),
+ __reserved_2 : 1 __attribute__ ((packed)),
+ WC : 1 __attribute__ ((packed)),
+ __reserved_1 : 53 __attribute__ ((packed));
+} MTRRcap_t __attribute__ ((packed));
+
+
+/*
+ * data type for the MTRRdefType register
+ */
+typedef struct {
+ __u64 Type : 8 __attribute__ ((packed)),
+ __reserved_1 : 2 __attribute__ ((packed)),
+ FE : 1 __attribute__ ((packed)),
+ E : 1 __attribute__ ((packed)),
+ __reserved_2 : 52 __attribute__ ((packed));
+} MTRRdefType_t __attribute__ ((packed));
+
+/* FIXME implement the entry struct */
+typedef struct MTRRfix64K_t {
+ __u64 raw;
+} MTRRfix64K_t __attribute__ ((packed));
+
+typedef struct MTRRfix16K_t {
+ __u64 raw;
+} MTRRfix16K_t __attribute__ ((packed));
+
+typedef struct MTRRfix4K_t {
+ __u64 raw;
+} MTRRfix4K_t __attribute__ ((packed));
+
+/*
+ * data type for a pair of variable MTRR registers
+ */
+typedef struct {
+ struct {
+ __u64 Type : 8 __attribute__ ((packed)),
+ __reserved_1 : 4 __attribute__ ((packed)),
+ PhysBase : 24 __attribute__ ((packed)),
+ __reserved_2 : 28 __attribute__ ((packed));
+ } MTRRphysBase __attribute__ ((packed));
+
+ struct {
+ __u64 __reserved_3 : 11 __attribute__ ((packed)),
+ V : 1 __attribute__ ((packed)),
+ PhysMask : 24 __attribute__ ((packed)),
+ __reserved_4 : 28 __attribute__ ((packed));
+ } MTRRphysMask __attribute__ ((packed));
+} MTRRvar_t __attribute__ ((packed));
+
+#define RAW_ACCESS64(data) (*(unsigned long long *)(&(data)))
+
+/*
+ * MTRR configuration struct
+ */
+struct mtrr_cntl_t {
+ MTRRcap_t MTRRcap; /* MTRR capability register */
+ MTRRdefType_t MTRRdefType; /* MTRR default type register */
+ MTRRfix64K_t fixed64; /* fixed length entries (raw data) */
+ MTRRfix16K_t fixed16[2];
+ MTRRfix4K_t fixed4[8];
+ MTRRvar_t variable[0]; /* variable type entries */
+};
+
+static struct mtrr_cntl_t *mtrrcntl = NULL;
+
+/*
+ * Deletes the variable MTRR *MTRRvar
+ */
+static inline void MTRRvar_delete(MTRRvar_t *MTRRvar)
+{
+ RAW_ACCESS64(MTRRvar->MTRRphysBase) = 0;
+ RAW_ACCESS64(MTRRvar->MTRRphysMask) = 0;
+}
+
+
+/*
+ * Sets the variable MTRR *MTRRvar
+ */
+static inline void MTRRvar_set(MTRRvar_t *MTRRvar, unsigned int type,
+ unsigned long base, unsigned long size)
+{
+ unsigned long val;
+ base >>= 12;
+ size >>= 12;
+
+ MTRRvar->MTRRphysBase.Type = type;
+ MTRRvar->MTRRphysBase.PhysBase = base;
+
+ MTRRvar->MTRRphysMask.V = 1;
+ val = 1<<25;
+ while (0 == (val & size)) val |= (val>>1);
+ MTRRvar->MTRRphysMask.PhysMask = val;
+}
+
+
+/*
+ * returns 1 if the variable MTRR entry *MTRRvar is valid, 0 otherwise
+ */
+static inline int MTRRvar_is_valid(const MTRRvar_t *MTRRvar)
+{
+ return MTRRvar->MTRRphysMask.V;
+}
+
+/*
+ * returns the type of the variable MTRR entry *MTRRvar
+ */
+static inline int MTRRvar_get_type(const MTRRvar_t *MTRRvar)
+{
+ return MTRRvar->MTRRphysBase.Type;
+}
+
+/*
+ * returns the base of the variable MTRR entry *MTRRvar
+ */
+static inline unsigned long long MTRRvar_get_base(const MTRRvar_t *MTRRvar)
+{
+ return ((unsigned long long)MTRRvar->MTRRphysBase.PhysBase) << 12;
+}
+
+/*
+ * returns the size of the variable MTRR entry *MTRRvar
+ */
+static inline unsigned long long MTRRvar_get_size(const MTRRvar_t *MTRRvar)
+{
+ if (MTRRvar->MTRRphysMask.PhysMask == 0) {
+ return 0;
+ } else {
+ unsigned long size = 1;
+ const unsigned long Mask = MTRRvar->MTRRphysMask.PhysMask;
+ while (0 == (Mask & size)) size <<= 1;
+ return ((unsigned long long)size) << 12;
+ }
+}
+
+/*
+ * returns the eflags register
+ */
+static inline int read_eflags(void)
+{
+ int ret;
+ asm volatile (
+ "pushfl\n\t"
+ "popl %%eax\n\t"
+ :"=a" (ret)
+ :
+ );
+ return ret;
+}
+
+/*
+ * writes the eflags register
+ */
+static inline void write_eflags(int flag)
+{
+ asm volatile (
+ "pushl %%eax\n\t"
+ "popfl\n\t"
+ :
+ :"a" (flag)
+ );
+}
+
+/*
+ * returns 1 if the mtrr's are supported by the current processor, 0 otherwise
+ */
+static inline int mtrr_detect(void) {
+ unsigned long flags;
+ int eflags;
+ int val;
+
+#define MSR_MASK 0x20
+#define MTRR_MASK 0x1000
+#define CPUID_MASK 0x200000
+ /* this function may be called before the cpu_data array has
+ been initialized */
+ save_flags(flags); sti();
+ eflags = read_eflags();
+ write_eflags(eflags ^ CPUID_MASK);
+ if (!((eflags ^ read_eflags()) & CPUID_MASK)) {
+ write_eflags(eflags);
+ restore_flags(flags);
+ return 0;
+ }
+ write_eflags(eflags);
+ restore_flags(flags);
+
+ /* get the cpuid level */
+ asm volatile (
+ "xorl %%eax,%%eax\n\t"
+ "cpuid"
+ :"=a"(val)::"ebx","ecx","edx"
+ );
+ if (val < 1) return 0;
+ /* get the x86_capability value */
+ asm volatile (
+ "movl $1,%%eax\n\t"
+ "cpuid"
+ :"=d"(val)::"ebx","ecx","eax"
+ );
+ if (!(val & MSR_MASK)) return 0;
+ if (!(val & MTRR_MASK)) return 0;
+
+ return 1;
+#undef MSR_MASK
+#undef MTRR_MASK
+#undef CPUID_MASK
+}
+
+
+/*
+ * reads the mtrr configuration of the actual processor and returns
+ * this configuration on sucess. returns NULL if an error occured or
+ * if mtrr's are not supported.
+ */
+static struct mtrr_cntl_t *read_mtrr_configuration (void) {
+ struct mtrr_cntl_t *mtrrcntl;
+ int i;
+ size_t size;
+ MTRRcap_t MTRRcap;
+
+ if (!mtrr_detect()) {
+ printk("/proc/mtrr: MTRR's are NOT supported\n");
+ return NULL;
+ }
+
+ RAW_ACCESS64(MTRRcap) = rdmsr(MTRR_CAP);
+
+/* #define DUMP_MTRR */
+#ifdef DUMP_MTRR
+ {
+ /* Written for a bugreport to Gigabyte ... */
+ inline void print_msr(int num) {
+ unsigned long long tmp = rdmsr(num);
+ printk("MSR #%#06x: 0x%08lx%08lx\n",
+ num , (unsigned long)(tmp >> 32),
+ (unsigned long)tmp);
+ }
+
+ print_msr(MTRR_CAP);
+ /* all variable type */
+ for (i=0;i < MTRRcap.VCNT;i++) {
+ print_msr(MTRR_VARIABLE+2*i);
+ print_msr(MTRR_VARIABLE+2*i+1);
+ }
+ /* all fixed type */
+ print_msr(MTRR_FIXED64K);
+ print_msr(MTRR_FIXED16K);
+ print_msr(MTRR_FIXED16K+1);
+ for (i=0;i<8;i++)
+ print_msr(MTRR_FIXED4K+i);
+ print_msr(MTRR_DEFTYPE);
+ }
+#endif
+
+ size = sizeof(struct mtrr_cntl_t) + sizeof(MTRRvar_t)*MTRRcap.VCNT;
+ if (NULL == (mtrrcntl = kmalloc(size, GFP_KERNEL))) return NULL;
+ memset(mtrrcntl, 0, size);
+
+ /* read MTRRcap register */
+ mtrrcntl->MTRRcap = MTRRcap;
+
+ /* read MTRRdefType register */
+ RAW_ACCESS64(mtrrcntl->MTRRdefType) = rdmsr(MTRR_DEFTYPE);
+
+ /* read fixed length entries */
+ if (mtrrcntl->MTRRdefType.E && mtrrcntl->MTRRdefType.FE) {
+ mtrrcntl->fixed64.raw = rdmsr(MTRR_FIXED64K);
+ mtrrcntl->fixed16[0].raw = rdmsr(MTRR_FIXED16K);
+ mtrrcntl->fixed16[1].raw = rdmsr(MTRR_FIXED16K+1);
+ for (i=0;i<8;i++)
+ mtrrcntl->fixed4[i].raw = rdmsr(MTRR_FIXED4K+i);
+ }
+
+ /* read variable length entries */
+ if (mtrrcntl->MTRRdefType.E) {
+ const int vcnt = mtrrcntl->MTRRcap.VCNT;
+ for (i = 0 ; i < vcnt ; i++) {
+ RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysBase) =
+ rdmsr(MTRR_VARIABLE + 2*i);
+ RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysMask) =
+ rdmsr(MTRR_VARIABLE + 2*i + 1);
+ }
+ }
+
+ return mtrrcntl;
+}
+
+/*
+ * initializes the global mtrr configuration
+ */
+/*__init_function(void init_mtrr_config(void)) FIXME*/
+void init_mtrr_config(void)
+{
+ mtrrcntl = read_mtrr_configuration();
+}
+
+
+/* write back and invalidate cache */
+static inline void wbinvd(void)
+{
+ asm volatile("wbinvd");
+}
+
+/* flush tlb's */
+static inline void flush__tlb(void)
+{
+ asm volatile (
+ "movl %%cr3, %%eax\n\t"
+ "movl %%eax, %%cr3\n\t"
+ :
+ :
+ : "memory", "eax");
+}
+
+/* clear page global enable and return previous value */
+static inline unsigned long clear_pge(void)
+{
+ unsigned long ret;
+ asm volatile (
+ "movl %%cr4, %%eax\n\t"
+ "movl %%eax, %%edx\n\t"
+ "andl $0x7f, %%edx\n\t"
+ "movl %%edx, %%cr4\n\t"
+ : "=a" (ret)
+ :
+ : "memory", "cc", "eax", "edx");
+ return ret;
+}
+
+/* restores page global enable bit */
+static inline void restore_pge(unsigned long cr4)
+{
+ asm volatile (
+ "movl %0, %%cr4\n\t"
+ :
+ : "r" (cr4)
+ : "memory");
+}
+
+/* ... */
+static inline void disable_cache(void)
+{
+ asm volatile (
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x40000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ :
+ :"memory", "cc", "eax");
+}
+
+/* ... */
+static inline void enable_cache(void)
+{
+ asm volatile (
+ "movl %%cr0, %%eax\n\t"
+ "andl $0xbfffffff, %%eax\n\t"
+ "movl %%eax, %%cr0"
+ :
+ :
+ :"memory", "cc", "eax");
+}
+
+/* clear the MTRRdefType.E and MTRRdefType.FE flag to disable these MTRR's */
+static inline void disable_mtrr(void)
+{
+ MTRRdefType_t MTRRdefType;
+
+ RAW_ACCESS64(MTRRdefType) = rdmsr(MTRR_DEFTYPE);
+ MTRRdefType.E = 0;
+ MTRRdefType.FE = 0;
+ wrmsr(MTRR_DEFTYPE, RAW_ACCESS64(MTRRdefType));
+}
+
+/*
+ * written from pseudocode from intel
+ * (PentiumPro Family Developers manual Volume 3, P 322)
+ *
+ */
+static inline unsigned long pre_mtrr_change(void)
+{
+ unsigned long cr4;
+
+ cr4 = clear_pge();
+
+ wbinvd();
+
+ disable_cache();
+
+ wbinvd();
+
+ flush__tlb();
+
+ disable_mtrr();
+
+ return cr4;
+}
+
+/*
+ * written from pseudocode from intel
+ * (PentiumPro Family Developers manual Volume 3, P 322)
+ */
+static inline void post_mtrr_change(MTRRdefType_t MTRRdefType,unsigned long cr4)
+{
+ wbinvd();
+
+ flush__tlb();
+
+ wrmsr(MTRR_DEFTYPE, RAW_ACCESS64(MTRRdefType));
+
+ enable_cache();
+
+ restore_pge(cr4);
+}
+
+/*
+ * writes all fixed mtrr's
+ */
+static inline void set_mtrr_fixed(void) {
+ int i;
+
+ wrmsr(MTRR_FIXED64K,mtrrcntl->fixed64.raw);
+ wrmsr(MTRR_FIXED16K+0,mtrrcntl->fixed16[0].raw);
+ wrmsr(MTRR_FIXED16K+1,mtrrcntl->fixed16[1].raw);
+ for (i=0;i<8;i++)
+ wrmsr(MTRR_FIXED4K+i,mtrrcntl->fixed4[i].raw);
+}
+
+/*
+ * writes all variable mtrr's
+ */
+static inline void set_mtrr_variable(void) {
+ int i;
+ const int vcnt = mtrrcntl->MTRRcap.VCNT;
+
+ for (i = 0 ; i < vcnt ; i++ ) {
+ wrmsr(MTRR_VARIABLE +2*i,
+ RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysBase));
+ wrmsr(MTRR_VARIABLE +2*i+1,
+ RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysMask));
+ }
+}
+
+
+/*
+ * compares the mtrr_cntl_t structure second with that set by
+ * the boot processor,
+ * returns 0 if equal,
+ * -1 if the structs are not initialized,
+ * 1 if they are different
+ *
+ * the *second struct is assumed to be local, it is not locked!
+ */
+static inline int compare_mtrr_configuration(struct mtrr_cntl_t *second) {
+ int i, result = 0;
+
+ if (NULL == mtrrcntl) { result = -1; goto end; }
+ if (NULL == second) { result = -1; goto end; }
+ if (RAW_ACCESS64(mtrrcntl->MTRRcap)
+ != RAW_ACCESS64(second->MTRRcap)) {
+ result = 1; goto end;
+ }
+
+ if (RAW_ACCESS64(mtrrcntl->MTRRdefType)
+ != RAW_ACCESS64(second->MTRRdefType)) {
+ result = 1; goto end;
+ }
+
+ if (mtrrcntl->fixed64.raw != second->fixed64.raw) {
+ result = 1; goto end;
+ }
+ if (mtrrcntl->fixed16[0].raw != second->fixed16[0].raw) {
+ result = 1; goto end;
+ }
+ if (mtrrcntl->fixed16[1].raw != second->fixed16[1].raw) {
+ result = 1; goto end;
+ }
+
+ for (i=0;i<8;i++)
+ if (mtrrcntl->fixed4[i].raw != second->fixed4[i].raw) {
+ result = 1; goto end;
+ }
+ {
+ const int vcnt = mtrrcntl->MTRRcap.VCNT;
+ for (i = 0; i < vcnt; i++) {
+ if (RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysBase) !=
+ RAW_ACCESS64(second->variable[i].MTRRphysBase)) {
+ result = 1; goto end;
+ }
+ if (RAW_ACCESS64(mtrrcntl->variable[i].MTRRphysMask) !=
+ RAW_ACCESS64(second->variable[i].MTRRphysMask)) {
+ result = 1; goto end;
+ }
+ }
+ }
+
+ end:
+
+ return result;
+}
+
+/*
+ * compares the mtrr configuration of the current processor with the
+ * main configuration and overwrites the mtrr's in the processor if they
+ * differ. (fixes a bug in the GA-686DX mainboard BIOS)
+ */
+void check_mtrr_config(void) {
+ unsigned long cr4;
+ unsigned long flags;
+ struct mtrr_cntl_t *this_cpu_setting;
+ int result;
+
+ save_flags(flags); sti();
+
+ /* if global struct is not initialized return */
+ if (mtrrcntl == NULL) {
+ restore_flags(flags);
+ return;
+ }
+
+ /* disable MTRR feature if this_cpu_setting == NULL */
+ /* read mtrr configuration of this cpu */
+ this_cpu_setting = read_mtrr_configuration();
+ if (this_cpu_setting == NULL) {
+ printk("/proc/mtrr: MTRR's are NOT supported by cpu %i.\n",
+ smp_processor_id());
+ restore_flags(flags);
+
+ return;
+ }
+ /* compare mtrr configuration */
+ result = compare_mtrr_configuration(this_cpu_setting);
+ kfree(this_cpu_setting);
+ /* return if mtrr setting is correct */
+ if (0 >= result) {
+ restore_flags(flags);
+ return;
+ }
+
+ /* prepare cpu's for setting mtrr's */
+ cr4 = pre_mtrr_change();
+
+ /* set all mtrr's */
+ set_mtrr_fixed();
+ set_mtrr_variable();
+
+ /* prepare cpu's for running */
+ post_mtrr_change(mtrrcntl->MTRRdefType, cr4);
+
+ restore_flags(flags);
+
+ printk("\nBIOS bug workaround: MTRR configuration changed on cpu "
+ "%i.\n", smp_processor_id());
+}
+
diff -u --recursive --new-file linux-2.0.33/arch/i386/kernel/smp.c linux-2.0.33-MTRR/arch/i386/kernel/smp.c
--- linux-2.0.33/arch/i386/kernel/smp.c Fri Nov 14 17:12:25 1997
+++ linux-2.0.33-MTRR/arch/i386/kernel/smp.c Mon Feb 9 21:18:20 1998
@@ -35,6 +35,9 @@
#include <asm/bitops.h>
#include <asm/pgtable.h>
#include <asm/smp.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif

/*
* Why isn't this somewhere standard ??
@@ -552,6 +555,14 @@
l=apic_read(APIC_SPIV);
l|=(1<<8); /* Enable */
apic_write(APIC_SPIV,l);
+
+#ifdef CONFIG_MTRR
+ /*
+ * checks the MTRR configuration of this application processor
+ */
+ check_mtrr_config();
+#endif
+
sti();
/*
* Get our bogomips.
diff -u --recursive --new-file linux-2.0.33/include/asm-i386/mtrr.h linux-2.0.33-MTRR/include/asm-i386/mtrr.h
--- linux-2.0.33/include/asm-i386/mtrr.h Thu Jan 1 01:00:00 1970
+++ linux-2.0.33-MTRR/include/asm-i386/mtrr.h Mon Feb 9 21:18:20 1998
@@ -0,0 +1,65 @@
+/* Generic MTRR (Memory Type Range Register) ioctls.
+
+ Copyright (C) 1997 Richard Gooch
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; 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.
+
+ modified by Mathias Fr"ohlich, Jan, 1998
+ <frohlich@na.uni-tuebingen.de>
+*/
+#ifndef _LINUX_MTRR_H
+#define _LINUX_MTRR_H
+
+/* These are the region types */
+#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_WRCOMB 1
+/*#define MTRR_TYPE_ 2*/
+/*#define MTRR_TYPE_ 3*/
+#define MTRR_TYPE_WRTHROUGH 4
+#define MTRR_TYPE_WRPROT 5
+#define MTRR_TYPE_WRBACK 6
+#define MTRR_NUM_TYPES 7
+
+static char *attrib_to_str (int x) __attribute__ ((unused));
+
+static char *attrib_to_str (int x)
+{
+ switch (x) {
+ case 0: return "uncachable";
+ case 1: return "write-combining";
+ case 4: return "write-through";
+ case 5: return "write-protect";
+ case 6: return "write-back";
+ default: return "?";
+ }
+} /* End Function attrib_to_str */
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_MTRR
+
+extern void check_mtrr_config(void);
+extern void init_mtrr_config(void);
+/* extern void set_mtrr_config(void); */
+
+#endif /* CONFIG_MTRR */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_MTRR_H */
diff -u --recursive --new-file linux-2.0.33/include/asm-i386/system.h linux-2.0.33-MTRR/include/asm-i386/system.h
--- linux-2.0.33/include/asm-i386/system.h Tue Dec 16 03:37:28 1997
+++ linux-2.0.33-MTRR/include/asm-i386/system.h Mon Feb 9 21:18:20 1998
@@ -296,4 +296,39 @@
void disable_hlt(void);
void enable_hlt(void);

+static __inline__ unsigned long long rdmsr(unsigned int msr)
+{
+ unsigned long long ret;
+ __asm__ __volatile__("rdmsr"
+ : "=A" (ret)
+ : "c" (msr));
+ return ret;
+}
+
+static __inline__ void wrmsr(unsigned int msr,unsigned long long val)
+{
+ __asm__ __volatile__("wrmsr"
+ : /* no Outputs */
+ : "c" (msr), "A" (val));
+}
+
+
+static __inline__ unsigned long long rdtsc(void)
+{
+ unsigned long long ret;
+ __asm__ __volatile__("rdtsc"
+ : "=A" (ret)
+ : /* no inputs */);
+ return ret;
+}
+
+static __inline__ unsigned long long rdpmc(unsigned int counter)
+{
+ unsigned long long ret;
+ __asm__ __volatile__("rdpmc"
+ : "=A" (ret)
+ : "c" (counter));
+ return ret;
+}
+
#endif
diff -u --recursive --new-file linux-2.0.33/init/main.c linux-2.0.33-MTRR/init/main.c
--- linux-2.0.33/init/main.c Thu Aug 14 19:30:08 1997
+++ linux-2.0.33-MTRR/init/main.c Mon Feb 9 21:18:20 1998
@@ -36,6 +36,9 @@
#ifdef CONFIG_ROOT_NFS
#include <linux/nfs_fs.h>
#endif
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif

#include <asm/bugs.h>

@@ -862,6 +865,11 @@
arch_syms_export();
sti();
check_bugs();
+
+#ifdef CONFIG_MTRR
+ init_mtrr_config();
+#endif
+

printk(linux_banner);
#ifdef __SMP__
--- cut ---

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen --             hps@tanstaafl.de
TANSTAAFL! Consulting - Unix, Internet, Security      

Hutweide 15 Fon.: 09131 / 50654-0 "There ain't no such D-91054 Buckenhof Fax.: 09131 / 50654-20 thing as a free Linux"

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/faq.html