summaryrefslogtreecommitdiff
path: root/src/cpu/x86/mtrr
diff options
context:
space:
mode:
authorYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
committerYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
commit13f1c2af8be2cd7f7e99a678f5d428a65b771811 (patch)
tree27cad5581f1fa150f573149d48e82f70ba1b1d9f /src/cpu/x86/mtrr
parent14cde9e96a777f9d75016a13b23fab0480515f58 (diff)
eric patch
1. x86_setup_mtrr take address bit. 2. generic ht, pcix, pcie beidge... 3. scan bus and reset_bus 4. ht read ctrl to decide if the ht chain is ready 5. Intel e7520 and e7525 support 6. new ich5r support 7. intel sb 6300 support. yhlu patch 1. split x86_setup_mtrrs to fixed and var 2. if (resource->flags & IORESOURCE_FIXED ) return; in device.c pick_largest_resource 3. in_conherent.c K8_SCAN_PCI_BUS git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1982 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/cpu/x86/mtrr')
-rw-r--r--src/cpu/x86/mtrr/earlymtrr.c6
-rw-r--r--src/cpu/x86/mtrr/mtrr.c132
2 files changed, 82 insertions, 56 deletions
diff --git a/src/cpu/x86/mtrr/earlymtrr.c b/src/cpu/x86/mtrr/earlymtrr.c
index c435b2edd5..105f7c49df 100644
--- a/src/cpu/x86/mtrr/earlymtrr.c
+++ b/src/cpu/x86/mtrr/earlymtrr.c
@@ -37,8 +37,8 @@ static void disable_var_mtrr(unsigned reg)
wrmsr(MTRRphysMask_MSR(reg), zero);
}
-static void set_var_mtrr(unsigned reg, unsigned base, unsigned size,
- unsigned type)
+static void set_var_mtrr(
+ unsigned reg, unsigned base, unsigned size, unsigned type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
@@ -76,7 +76,7 @@ static void do_early_mtrr_init(const unsigned long *mtrr_msrs)
msr.lo = 0;
msr.hi = 0;
unsigned long msr_nr;
- for (msr_addr = mtrr_msrs; (msr_nr = *msr_addr); msr_addr++) {
+ for(msr_addr = mtrr_msrs; (msr_nr = *msr_addr); msr_addr++) {
wrmsr(msr_nr, msr);
}
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 59f9ca1e91..1226713cf5 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -22,9 +22,14 @@
*
* Reference: Intel Architecture Software Developer's Manual, Volume 3: System Programming
*/
+
/*
- 2005.1 yhlu add NC support to spare mtrrs for 64G memory stored
+ 2005.1 yhlu add NC support to spare mtrrs for 64G memory above installed
+ 2005.6 Eric add address bit in x86_setup_mtrrs
+ 2005.6 yhlu split x86_setup_var_mtrrs and x86_setup_fixed_mtrrs,
+ for AMD, it will not use x86_setup_fixed_mtrrs
*/
+
#include <stddef.h>
#include <console/console.h>
#include <device/device.h>
@@ -32,19 +37,6 @@
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
-#warning "FIXME I do not properly handle address more than 36 physical address bits"
-
-//#define k8 0
-#define k8 1
-
-#if k8
-# define ADDRESS_BITS 40
-#else
-# define ADDRESS_BITS 36
-#endif
-#define ADDRESS_BITS_HIGH (ADDRESS_BITS - 32)
-#define ADDRESS_MASK_HIGH ((1u << ADDRESS_BITS_HIGH) - 1)
-
static unsigned int mtrr_msr[] = {
MTRRfix64K_00000_MSR, MTRRfix16K_80000_MSR, MTRRfix16K_A0000_MSR,
MTRRfix4K_C0000_MSR, MTRRfix4K_C8000_MSR, MTRRfix4K_D0000_MSR, MTRRfix4K_D8000_MSR,
@@ -52,7 +44,7 @@ static unsigned int mtrr_msr[] = {
};
-static void enable_fixed_mtrr(void)
+void enable_fixed_mtrr(void)
{
msr_t msr;
@@ -71,21 +63,26 @@ static void enable_var_mtrr(void)
}
/* setting variable mtrr, comes from linux kernel source */
-static void set_var_mtrr(unsigned int reg, unsigned long basek, unsigned long sizek, unsigned char type)
+static void set_var_mtrr(
+ unsigned int reg, unsigned long basek, unsigned long sizek,
+ unsigned char type, unsigned address_bits)
{
msr_t base, mask;
+ unsigned address_mask_high;
+
+ address_mask_high = ((1u << (address_bits - 32u)) - 1u);
base.hi = basek >> 22;
base.lo = basek << 10;
- //printk_debug("ADDRESS_MASK_HIGH=%#x\n", ADDRESS_MASK_HIGH);
+ printk_spew("ADDRESS_MASK_HIGH=%#x\n", address_mask_high);
if (sizek < 4*1024*1024) {
- mask.hi = ADDRESS_MASK_HIGH;
+ mask.hi = address_mask_high;
mask.lo = ~((sizek << 10) -1);
}
else {
- mask.hi = ADDRESS_MASK_HIGH & (~((sizek >> 22) -1));
+ mask.hi = address_mask_high & (~((sizek >> 22) -1));
mask.lo = 0;
}
@@ -219,7 +216,7 @@ static unsigned fixed_mtrr_index(unsigned long addrk)
static unsigned int range_to_mtrr(unsigned int reg,
unsigned long range_startk, unsigned long range_sizek,
- unsigned long next_range_startk, unsigned char type)
+ unsigned long next_range_startk, unsigned char type, unsigned address_bits)
{
if (!range_sizek || (reg >= BIOS_MTRRS)) {
return reg;
@@ -235,11 +232,11 @@ static unsigned int range_to_mtrr(unsigned int reg,
}
sizek = 1 << align;
printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type %s\n",
- reg, range_startk >>10, sizek >> 10,
- (type==MTRR_TYPE_UNCACHEABLE) ? "NC" :
- ((type==MTRR_TYPE_WRBACK) ? "WB" : "Other")
+ reg, range_startk >>10, sizek >> 10,
+ (type==MTRR_TYPE_UNCACHEABLE)?"UC":
+ ((type==MTRR_TYPE_WRBACK)?"WB":"Other")
);
- set_var_mtrr(reg++, range_startk, sizek, type);
+ set_var_mtrr(reg++, range_startk, sizek, type, address_bits);
range_startk += sizek;
range_sizek -= sizek;
if (reg >= BIOS_MTRRS)
@@ -279,6 +276,7 @@ struct var_mtrr_state {
unsigned long range_startk, range_sizek;
unsigned int reg;
unsigned long hole_startk, hole_sizek;
+ unsigned address_bits;
};
void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
@@ -300,47 +298,68 @@ void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
}
/* Write the range mtrrs */
if (state->range_sizek != 0) {
- if(state->hole_sizek == 0) {
- // we need to put that on to hole.
- unsigned long endk = basek + sizek;
+ if (state->hole_sizek == 0) {
+ /* We need to put that on to hole */
+ unsigned long endk = basek + sizek;
state->hole_startk = state->range_startk + state->range_sizek;
- state->hole_sizek = basek - state->hole_startk;
- state->range_sizek = endk - state->range_startk;
+ state->hole_sizek = basek - state->hole_startk;
+ state->range_sizek = endk - state->range_startk;
return;
}
- state->reg = range_to_mtrr(state->reg, state->range_startk, state->range_sizek, basek, MTRR_TYPE_WRBACK);
- state->reg = range_to_mtrr(state->reg, state->hole_startk, state->hole_sizek, basek, MTRR_TYPE_UNCACHEABLE);
+ state->reg = range_to_mtrr(state->reg, state->range_startk,
+ state->range_sizek, basek, MTRR_TYPE_WRBACK, state->address_bits);
+ state->reg = range_to_mtrr(state->reg, state->hole_startk,
+ state->hole_sizek, basek, MTRR_TYPE_UNCACHEABLE, state->address_bits);
state->range_startk = 0;
state->range_sizek = 0;
state->hole_startk = 0;
state->hole_sizek = 0;
}
- /* Allocate an msr */
+ /* Allocate an msr */
+ printk_spew(" Allocate an msr - basek = %d, sizek = %d,\n", basek, sizek);
state->range_startk = basek;
state->range_sizek = sizek;
}
-void x86_setup_mtrrs(void)
+void x86_setup_fixed_mtrrs(void)
+{
+ /* Try this the simple way of incrementally adding together
+ * mtrrs. If this doesn't work out we can get smart again
+ * and clear out the mtrrs.
+ */
+ struct var_mtrr_state var_state;
+
+ printk_debug("\n");
+ /* Initialized the fixed_mtrrs to uncached */
+ printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n",
+ 0, NUM_FIXED_RANGES);
+ set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHEABLE);
+
+ /* Now see which of the fixed mtrrs cover ram.
+ */
+ search_global_resources(
+ IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
+ set_fixed_mtrr_resource, NULL);
+ printk_debug("DONE fixed MTRRs\n");
+
+ /* enable fixed MTRR */
+ printk_spew("call enable_fixed_mtrr()\n");
+ enable_fixed_mtrr();
+
+}
+void x86_setup_var_mtrrs(unsigned address_bits)
+/* this routine needs to know how many address bits a given processor
+ * supports. CPUs get grumpy when you set too many bits in
+ * their mtrr registers :( I would generically call cpuid here
+ * and find out how many physically supported but some cpus are
+ * buggy, and report more bits then they actually support.
+ */
{
/* Try this the simple way of incrementally adding together
* mtrrs. If this doesn't work out we can get smart again
* and clear out the mtrrs.
*/
struct var_mtrr_state var_state;
-#if !k8
- printk_debug("\n");
- /* Initialized the fixed_mtrrs to uncached */
- printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n",
- 0, NUM_FIXED_RANGES);
- set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHEABLE);
-
- /* Now see which of the fixed mtrrs cover ram.
- */
- search_global_resources(
- IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
- set_fixed_mtrr_resource, NULL);
- printk_debug("DONE fixed MTRRs\n");
-#endif
/* Cache as many memory areas as possible */
/* FIXME is there an algorithm for computing the optimal set of mtrrs?
@@ -351,28 +370,35 @@ void x86_setup_mtrrs(void)
var_state.hole_startk = 0;
var_state.hole_sizek = 0;
var_state.reg = 0;
+ var_state.address_bits = address_bits;
search_global_resources(
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
set_var_mtrr_resource, &var_state);
/* Write the last range */
- var_state.reg = range_to_mtrr(var_state.reg, var_state.range_startk, var_state.range_sizek, 0, MTRR_TYPE_WRBACK);
- var_state.reg = range_to_mtrr(var_state.reg, var_state.hole_startk, var_state.hole_sizek, 0, MTRR_TYPE_UNCACHEABLE);
+ var_state.reg = range_to_mtrr(var_state.reg, var_state.range_startk,
+ var_state.range_sizek, 0, MTRR_TYPE_WRBACK, var_state.address_bits);
+ var_state.reg = range_to_mtrr(var_state.reg, var_state.hole_startk,
+ var_state.hole_sizek, 0, MTRR_TYPE_UNCACHEABLE, var_state.address_bits);
printk_debug("DONE variable MTRRs\n");
printk_debug("Clear out the extra MTRR's\n");
/* Clear out the extra MTRR's */
while(var_state.reg < MTRRS) {
- set_var_mtrr(var_state.reg++, 0, 0, 0);
+ set_var_mtrr(var_state.reg++, 0, 0, 0, var_state.address_bits);
}
- /* enable fixed MTRR */
- printk_spew("call enable_fixed_mtrr()\n");
- enable_fixed_mtrr();
printk_spew("call enable_var_mtrr()\n");
enable_var_mtrr();
printk_spew("Leave %s\n", __FUNCTION__);
post_code(0x6A);
}
+void x86_setup_mtrrs(unsigned address_bits)
+{
+ x86_setup_fixed_mtrrs();
+ x86_setup_var_mtrrs(address_bits);
+}
+
+
int x86_mtrr_check(void)
{
/* Only Pentium Pro and later have MTRR */