summaryrefslogtreecommitdiff
path: root/src/cpu/p6
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/p6')
-rw-r--r--src/cpu/p6/Config.lb1
-rw-r--r--src/cpu/p6/boot_cpu.c2
-rw-r--r--src/cpu/p6/earlymtrr.c10
-rw-r--r--src/cpu/p6/mtrr.c37
-rw-r--r--src/cpu/p6/pgtbl.c91
5 files changed, 131 insertions, 10 deletions
diff --git a/src/cpu/p6/Config.lb b/src/cpu/p6/Config.lb
index c9d483480a..f6e9777bcd 100644
--- a/src/cpu/p6/Config.lb
+++ b/src/cpu/p6/Config.lb
@@ -3,4 +3,5 @@ uses INTEL_PPRO_MTRR
dir /cpu/p5
object cpufixup.o
object mtrr.o
+object pgtbl.o
#object l2_cache.o
diff --git a/src/cpu/p6/boot_cpu.c b/src/cpu/p6/boot_cpu.c
index 803eecdd5d..77b060b219 100644
--- a/src/cpu/p6/boot_cpu.c
+++ b/src/cpu/p6/boot_cpu.c
@@ -2,8 +2,6 @@
int boot_cpu(void)
{
- volatile unsigned long *local_apic;
- unsigned long apic_id;
int bsp;
msr_t msr;
msr = rdmsr(0x1b);
diff --git a/src/cpu/p6/earlymtrr.c b/src/cpu/p6/earlymtrr.c
index f352f3d791..df74f905c8 100644
--- a/src/cpu/p6/earlymtrr.c
+++ b/src/cpu/p6/earlymtrr.c
@@ -51,7 +51,7 @@ static void early_mtrr_init(void)
/* Disable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000000;
- wrmsr(0x2ff, msr);
+ wrmsr(MTRRdefType_MSR, msr);
/* Invalidate the cache again */
asm volatile ("invd");
@@ -65,19 +65,19 @@ static void early_mtrr_init(void)
wrmsr(*msr_addr, msr);
}
- /* Enable caching for 0 - 128MB using variable mtrr */
+ /* Enable caching for 0 - 1MB using variable mtrr */
msr = rdmsr(0x200);
msr.hi &= 0xfffffff0;
msr.hi |= 0x00000000;
msr.lo &= 0x00000f00;
- msr.lo |= 0x00000006;
+ msr.lo |= 0x00000000 | MTRR_TYPE_WRBACK;
wrmsr(0x200, msr);
msr = rdmsr(0x201);
msr.hi &= 0xfffffff0;
msr.hi |= 0x0000000f;
msr.lo &= 0x000007ff;
- msr.lo |= 0xf0000800;
+ msr.lo |= (~((CONFIG_LB_MEM_TOPK << 10) - 1)) | 0x800;
wrmsr(0x201, msr);
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
@@ -98,7 +98,7 @@ static void early_mtrr_init(void)
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
- wrmsr(0x2ff, msr);
+ wrmsr(MTRRdefType_MSR, msr);
/* Enable the cache */
cr0 = read_cr0();
diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c
index ac6fd1db37..7e2eb06e95 100644
--- a/src/cpu/p6/mtrr.c
+++ b/src/cpu/p6/mtrr.c
@@ -104,7 +104,8 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l
if (sizek < 4*1024*1024) {
mask.hi = ADDRESS_MASK_HIGH;
mask.lo = ~((sizek << 10) -1);
- } else {
+ }
+ else {
mask.hi = ADDRESS_MASK_HIGH & (~((sizek >> 22) -1));
mask.lo = 0;
}
@@ -131,6 +132,36 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l
enable_cache();
}
+/* setting variable mtrr, comes from linux kernel source */
+void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type)
+{
+ if (reg >= 8)
+ return;
+
+ // it is recommended that we disable and enable cache when we
+ // do this.
+ disable_cache();
+ if (size == 0) {
+ /* The invalid bit is kept in the mask, so we simply clear the
+ relevant mask register to disable a range. */
+ msr_t zero;
+ zero.lo = zero.hi = 0;
+ wrmsr (MTRRphysMask_MSR(reg), zero);
+ } else {
+ /* Bit 32-35 of MTRRphysMask should be set to 1 */
+ msr_t basem, maskm;
+ basem.lo = base | type;
+ basem.hi = 0;
+ maskm.lo = ~(size - 1) | 0x800;
+ maskm.hi = 0x0F;
+ wrmsr (MTRRphysBase_MSR(reg), basem);
+ wrmsr (MTRRphysMask_MSR(reg), maskm);
+ }
+
+ // turn cache back on.
+ enable_cache();
+}
+
/* fms: find most sigificant bit set, stolen from Linux Kernel Source. */
static inline unsigned int fms(unsigned int x)
{
@@ -250,7 +281,7 @@ static unsigned int range_to_mtrr(unsigned int reg,
}
sizek = 1 << align;
printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n",
- reg, range_startk >>10, sizek >> 10);
+ reg, range_startk >>10, sizek >> 10);
intel_set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK);
range_startk += sizek;
range_sizek -= sizek;
@@ -274,7 +305,7 @@ void setup_mtrrs(struct mem_range *mem)
/* 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_UNCACHABLE);
+ set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHEABLE);
/* Now see which of the fixed mtrrs cover ram.
*/
diff --git a/src/cpu/p6/pgtbl.c b/src/cpu/p6/pgtbl.c
new file mode 100644
index 0000000000..e996dd0e69
--- /dev/null
+++ b/src/cpu/p6/pgtbl.c
@@ -0,0 +1,91 @@
+#include <console/console.h>
+#include <smp/start_stop.h>
+#include <cpu/p6/pgtbl.h>
+
+static void paging_off(void)
+{
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7FFFFFFF, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ /* Disable pae */
+ "movl %%cr4, %%eax\n\t"
+ "andl $0xFFFFFFDF, %%eax\n\t"
+ :
+ :
+ : "eax"
+ );
+}
+
+static void paging_on(void *pdp)
+{
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable pae */
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000020, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pdp)
+ : "eax"
+ );
+}
+
+void *map_2M_page(int cpu_index, unsigned long page)
+{
+ struct pde {
+ uint32_t addr_lo;
+ uint32_t addr_hi;
+ } __attribute__ ((packed));
+ struct pg_table {
+ struct pde pd[2048];
+ struct pde pdp[512];
+ } __attribute__ ((packed));
+ static struct pg_table pgtbl[CONFIG_MAX_CPUS] __attribute__ ((aligned(4096)));
+ static unsigned long mapped_window[CONFIG_MAX_CPUS];
+ unsigned long window;
+ void *result;
+ int i;
+ if ((cpu_index < 0) || (cpu_index >= CONFIG_MAX_CPUS)) {
+ return MAPPING_ERROR;
+ }
+ window = page >> 10;
+ if (window != mapped_window[cpu_index]) {
+ paging_off();
+ if (window > 1) {
+ struct pde *pd, *pdp;
+ /* Point the page directory pointers at the page directories */
+ memset(&pgtbl[cpu_index].pdp, 0, sizeof(pgtbl[cpu_index].pdp));
+ pd = pgtbl[cpu_index].pd;
+ pdp = pgtbl[cpu_index].pdp;
+ pdp[0].addr_lo = ((uint32_t)&pd[512*0])|1;
+ pdp[1].addr_lo = ((uint32_t)&pd[512*1])|1;
+ pdp[2].addr_lo = ((uint32_t)&pd[512*2])|1;
+ pdp[3].addr_lo = ((uint32_t)&pd[512*3])|1;
+ /* The first half of the page table is identity mapped */
+ for(i = 0; i < 1024; i++) {
+ pd[i].addr_lo = ((i & 0x3ff) << 21)| 0xE3;
+ pd[i].addr_hi = 0;
+ }
+ /* The second half of the page table holds the mapped page */
+ for(i = 1024; i < 2048; i++) {
+ pd[i].addr_lo = ((window & 1) << 31) | ((i & 0x3ff) << 21) | 0xE3;
+ pd[i].addr_hi = (window >> 1);
+ }
+ paging_on(pdp);
+ }
+ mapped_window[cpu_index] = window;
+ }
+ if (window == 0) {
+ result = (void *)(page << 21);
+ } else {
+ result = (void *)(0x80000000 | ((page & 0x3ff) << 21));
+ }
+ return result;
+}