patch-2.2.15 linux/arch/i386/kernel/mtrr.c
Next file: linux/arch/i386/kernel/process.c
Previous file: linux/arch/i386/kernel/irq.c
Back to the patch index
Back to the overall index
- Lines: 267
- Date:
Fri Apr 21 12:45:45 2000
- Orig file:
v2.2.14/arch/i386/kernel/mtrr.c
- Orig date:
Sat Aug 28 20:00:53 1999
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
@@ -139,41 +139,41 @@
Changed locking to spin with reschedule.
Made use of new <smp_call_function>.
v1.28
- 19990201 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990201 Zoltán Böszörményi <zboszor@mail.externet.hu>
Extended the driver to be able to use Cyrix style ARRs.
19990204 Richard Gooch <rgooch@atnf.csiro.au>
Restructured Cyrix support.
v1.29
- 19990204 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990204 Zoltán Böszörményi <zboszor@mail.externet.hu>
Refined ARR support: enable MAPEN in set_mtrr_prepare()
and disable MAPEN in set_mtrr_done().
19990205 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.30
- 19990208 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990208 Zoltán Böszörményi <zboszor@mail.externet.hu>
Protect plain 6x86s (and other processors without the
Page Global Enable feature) against accessing CR4 in
set_mtrr_prepare() and set_mtrr_done().
19990210 Richard Gooch <rgooch@atnf.csiro.au>
Turned <set_mtrr_up> and <get_mtrr> into function pointers.
v1.31
- 19990212 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990212 Zoltán Böszörményi <zboszor@mail.externet.hu>
Major rewrite of cyrix_arr_init(): do not touch ARRs,
leave them as the BIOS have set them up.
Enable usage of all 8 ARRs.
Avoid multiplications by 3 everywhere and other
code clean ups/speed ups.
- 19990213 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990213 Zoltán Böszörményi <zboszor@mail.externet.hu>
Set up other Cyrix processors identical to the boot cpu.
Since Cyrix don't support Intel APIC, this is l'art pour l'art.
Weigh ARRs by size:
If size <= 32M is given, set up ARR# we were given.
If size > 32M is given, set up ARR7 only if it is free,
fail otherwise.
- 19990214 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990214 Zoltán Böszörményi <zboszor@mail.externet.hu>
Also check for size >= 256K if we are to set up ARR7,
mtrr_add() returns the value it gets from set_mtrr()
- 19990218 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990218 Zoltán Böszörményi <zboszor@mail.externet.hu>
Remove Cyrix "coma bug" workaround from here.
Moved to linux/arch/i386/kernel/setup.c and
linux/include/asm-i386/bugs.h
@@ -187,7 +187,7 @@
19990305 Richard Gooch <rgooch@atnf.csiro.au>
Temporarily disable AMD support now MTRR capability flag is set.
v1.32
- 19990308 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990308 Zoltán Böszörményi <zboszor@mail.externet.hu>
Adjust my changes (19990212-19990218) to Richard Gooch's
latest changes. (19990228-19990305)
v1.33
@@ -197,7 +197,7 @@
Support K6-II/III based on Alan Cox's <alan@redhat.com> patches.
v1.34
19990511 Bart Hartgers <bart@etpmod.phys.tue.nl>
- Support Centaur C6 MCR's.
+ Support Centaur C6 MCRs.
19990512 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.35
@@ -210,6 +210,9 @@
19990819 Alan Cox <alan@redhat.com>
Tested Zoltan's changes on a pre production Athlon - 100%
success. Fixed one fall through check to be Intel only.
+ 19991116 Bart Hartgers <bart@etpmod.phys.tue.nl>
+ Changed Centaur/IDT WinChip support to include WinChip 2.
+ (WC 2 kindly provided by IDT).
*/
#include <linux/types.h>
@@ -581,18 +584,31 @@
return;
} /* End Function amd_get_mtrr */
-static struct
+static struct CENTAUR_MCR_CTX
{
- unsigned long high;
- unsigned long low;
-} centaur_mcr[8];
+ unsigned type_bits[MTRR_NUM_TYPES];
+ struct {
+ u32 low;
+ u32 high;
+ } mcr[8];
+} *centaur_ctx=NULL;
static void centaur_get_mcr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
- *base = centaur_mcr[reg].high & 0xfffff000;
- *size = (~(centaur_mcr[reg].low & 0xfffff000))+1;
- *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */
+ unsigned i;
+ u32 tb;
+ tb = centaur_ctx->mcr[reg].low & 0xfff;
+ *base = centaur_ctx->mcr[reg].high & 0xfffff000;
+ *size = (~(centaur_ctx->mcr[reg].low & 0xfffff000))+1;
+ if (*size) {
+ for( i=0; i<MTRR_NUM_TYPES; ++i)
+ if (centaur_ctx->type_bits[i]==tb) {
+ *type = (mtrr_type) i;
+ return;
+ }
+ *size = 0;
+ }
} /* End Function centaur_get_mcr */
static void (*get_mtrr) (unsigned int reg, unsigned long *base,
@@ -716,6 +732,7 @@
unsigned long low, high;
if (do_safe) set_mtrr_prepare( &ctxt );
+
if (size == 0)
{
/* Disable */
@@ -724,12 +741,13 @@
else
{
high = base & 0xfffff000; /* base works on 4K pages... */
- low = ((~(size-1))&0xfffff000);
- low |= 0x1f; /* only support write-combining... */
+ low = ((~(size-1))&0xfffff000)|(centaur_ctx->type_bits[type]);
}
- centaur_mcr[reg].high = high;
- centaur_mcr[reg].low = low;
+ centaur_ctx->mcr[reg].high = high;
+ centaur_ctx->mcr[reg].low = low;
+
wrmsr (0x110 + reg, low, high);
+
if (do_safe) set_mtrr_done( &ctxt );
} /* End Function centaur_set_mtrr_up */
@@ -1078,6 +1096,12 @@
unsigned long lbase, lsize, last;
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
+ if (type >= MTRR_NUM_TYPES)
+ {
+ printk ("mtrr: type: %u illegal\n", type);
+ return -EINVAL;
+ }
+
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
@@ -1113,13 +1137,12 @@
}
if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
{
- if (type != MTRR_TYPE_WRCOMB)
- {
- printk ("mtrr: only write-combining is supported\n");
+ if (centaur_ctx->type_bits[type]==0) {
+ printk ("mtrr: type not supported\n");
return -EINVAL;
}
}
- else if (base + size < 0x100000)
+ else if (base + size < 0x100000) /* Cyrix */
{
printk ("mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n",
base, size);
@@ -1141,11 +1164,6 @@
return -EINVAL;
/*break;*/
}
- if (type >= MTRR_NUM_TYPES)
- {
- printk ("mtrr: type: %u illegal\n", type);
- return -EINVAL;
- }
/* If the type is WC, check that this processor supports it */
if ( (type == MTRR_TYPE_WRCOMB) && !have_wrcomb () )
{
@@ -1172,7 +1190,8 @@
/* New region is enclosed by an existing region */
if (ltype != type)
{
- if (type == MTRR_TYPE_UNCACHABLE) continue;
+ if ((boot_cpu_data.x86_vendor != X86_VENDOR_CENTAUR) &&
+ (type == MTRR_TYPE_UNCACHABLE)) continue;
spin_unlock (&main_lock);
printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n",
base, size, attrib_to_str (ltype), attrib_to_str (type) );
@@ -1652,7 +1671,51 @@
{
unsigned i;
struct set_mtrr_context ctxt;
-
+ u32 low,high;
+ u32 mcr_ctrl_value;
+ unsigned mcr_type;
+ /* Deduce the MCR traits type for this processor.
+ * The documentation of the WinChip 2 suggests that we can read the
+ * MCR_CTRL register for all WinChips, but this hangs on my C6.
+ * -> Work around this.
+ */
+ if ((boot_cpu_data.x86 == 5) && (boot_cpu_data.x86_model == 4)) {
+ /* C6 */
+ mcr_type = 0;
+ } else {
+ rdmsr (0x120, low, high );
+ mcr_type = (low>>17)&0x7;
+ }
+ centaur_ctx = kmalloc( sizeof( struct CENTAUR_MCR_CTX ), GFP_KERNEL );
+ if (centaur_ctx == NULL) {
+ printk("mtrr: Could not allocate memory. Disabling MTRR.\n");
+ boot_cpu_data.x86_capability &= ~X86_FEATURE_MTRR;
+ return;
+ }
+ for( i=0; i<MTRR_NUM_TYPES; ++i) {
+ centaur_ctx->type_bits[i] = 0;
+ }
+ switch( mcr_type ) {
+ case 0:
+ centaur_ctx->type_bits[ MTRR_TYPE_WRCOMB ] = 0x0f;
+ centaur_ctx->type_bits[ MTRR_TYPE_WRBACK ] = 0x1f;
+ mcr_ctrl_value = 0x01f0001f;
+ break;
+ case 1:
+ centaur_ctx->type_bits[ MTRR_TYPE_UNCACHABLE ] = 0x02;
+ centaur_ctx->type_bits[ MTRR_TYPE_WRCOMB ] = 0x13;
+ centaur_ctx->type_bits[ MTRR_TYPE_WRTHROUGH ] = 0x11;
+ centaur_ctx->type_bits[ MTRR_TYPE_WRBACK ] = 0x19;
+ mcr_ctrl_value = 0x01f2005f;
+ break;
+ default:
+ kfree( centaur_ctx );
+ centaur_ctx = NULL;
+ printk ("mtrr: Centaur MCR traits version %u not supported. "
+ "Disabling MTRR.\n", mcr_type);
+ boot_cpu_data.x86_capability &= ~X86_FEATURE_MTRR;
+ return;
+ }
set_mtrr_prepare (&ctxt);
/* Unfortunately, MCR's are read-only, so there is no way to
* find out what the bios might have done.
@@ -1661,14 +1724,16 @@
* This way we are sure that the centaur_mcr array contains the actual
* values. The disadvantage is that any BIOS tweaks are thus undone.
*/
+ /* switch off MCR's first */
+ wrmsr (0x120, 0, 0 );
for (i = 0; i < 8; ++i)
{
- centaur_mcr[i].high = 0;
- centaur_mcr[i].low = 0;
+ centaur_ctx->mcr[i].high = 0;
+ centaur_ctx->mcr[i].low = 0;
wrmsr (0x110 + i , 0, 0);
}
/* Throw the main write-combining switch... */
- wrmsr (0x120, 0x01f0001f, 0);
+ wrmsr (0x120, mcr_ctrl_value, 0);
set_mtrr_done (&ctxt);
} /* End Function centaur_mcr_init */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)