[PATCH][2.6] Make MTRR init conform with recommended procedure

From: Zwane Mwaikambo
Date: Sun Aug 10 2003 - 16:19:41 EST


Hi Dave,
This is a patch to make the MTRR initialisation more conformant
with what is stated in volume 3 of (10-36 Memory Cache Control). The most
notable change is entering the no-fill cache mode before clearing the PGE
bit in cr4. Intel also states that we should do the cache flush via the
cr3 register shuffle. If there is a problem with the patch please don't
hesitate to beat me vigorously with a clue-by-four.

It has been tested on a 3x Pentium 133, 8x PIII Xeon 700, 1x Celeron 550 and 32x
PIII 500 NUMAQ (hardware courtesy of OSDL)

Index: linux-2.6.0-test3-huge_kpage/arch/i386/kernel/cpu/mtrr/generic.c
===================================================================
RCS file: /build/cvsroot/linux-2.6.0-test3/arch/i386/kernel/cpu/mtrr/generic.c,v
retrieving revision 1.1.1.1
diff -u -p -B -r1.1.1.1 generic.c
--- linux-2.6.0-test3-huge_kpage/arch/i386/kernel/cpu/mtrr/generic.c 10 Aug 2003 08:41:39 -0000 1.1.1.1
+++ linux-2.6.0-test3-huge_kpage/arch/i386/kernel/cpu/mtrr/generic.c 10 Aug 2003 20:24:49 -0000
@@ -8,6 +8,7 @@
#include <asm/msr.h>
#include <asm/system.h>
#include <asm/cpufeature.h>
+#include <asm/tlbflush.h>
#include "mtrr.h"

struct mtrr_state {
@@ -241,19 +242,21 @@ static void prepare_set(void)
more invasive changes to the way the kernel boots */
spin_lock(&set_atomicity_lock);

+ /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
+ cr0 = read_cr0() | 0x40000000; /* set CD flag */
+ wbinvd();
+ write_cr0(cr0);
+ wbinvd();
+
/* Save value of CR4 and clear Page Global Enable (bit 7) */
if ( cpu_has_pge ) {
cr4 = read_cr4();
write_cr4(cr4 & (unsigned char) ~(1 << 7));
}

- /* Disable and flush caches. Note that wbinvd flushes the TLBs as
- a side-effect */
- cr0 = read_cr0() | 0x40000000;
- wbinvd();
- write_cr0(cr0);
- wbinvd();
-
+ /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
+ __flush_tlb();
+
/* Save MTRR state */
rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);

@@ -265,6 +268,7 @@ static void post_set(void)
{
/* Flush caches and TLBs */
wbinvd();
+ __flush_tlb();

/* Intel (P6) standard MTRRs */
wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/