Setup the MTRRs in stage1 so that memory and cache are available throughout

stage2. This fixes problems with VGA graphics ROMs access to 0xA0000-0xBFFFF.
It also sets all system memory to WriteBack cached and sets the ROM
area to cached.

Signed-off-by: Marc Jones <marcj303@gmail.com>
Acked-by: Peter Stuge <peter@stuge.se>



git-svn-id: svn://coreboot.org/repository/coreboot-v3@1128 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Marc Jones 2009-02-10 22:40:10 +00:00
commit a794edb17b
6 changed files with 169 additions and 99 deletions

View file

@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Advanced Micro Devices, Inc.
* Copyright (C) 2009 Marc Jones <marcj303@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -29,31 +30,136 @@
#include <stage1.h>
/**
* Set the MTRR for initial ram access.
* be warned, this will be used by core other than core 0/node 0 or core0/node0 when cpu_reset.
* This warning has some significance I don't yet understand.
* Set the MTRRs of the current core for initial ram access.
* Be warned, this function is used by the BSP and all AP cores. TOM and TOM2
* of the calling core must be setup. This function may be called several times
* depending on MEM_TRAIN_SEQ.
*/
void set_init_ram_access(void)
void set_mtrr_ram_access(void)
{
stage1_set_var_mtrr(0, 0x00000000, CONFIG_CBMEMK << 10, MTRR_TYPE_WRBACK);
struct msr msr;
disable_cache();
/* 0 - 640KB */
stage1_set_fix_mtrr(MTRRfix64K_00000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix16K_80000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
/* 0xA0000 - 0xC0000 (UC to video card) */
stage1_set_fix_mtrr(MTRRfix16K_A0000_MSR, MTRR_TYPE_UNCACHEABLE);
/* 0xC0000 - 1MB */
stage1_set_fix_mtrr(MTRRfix4K_C0000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_C8000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_D0000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_D8000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_E0000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_E8000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_F0000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
stage1_set_fix_mtrr(MTRRfix4K_F8000_MSR,
MTRR_READ_MEM | MTRR_WRITE_MEM | MTRR_TYPE_WRBACK);
/* 1MB - TOM */
msr = rdmsr(TOP_MEM);
stage1_set_var_mtrr_x(0, 0x00100000, 0x0, msr.lo, msr.hi, MTRR_TYPE_WRBACK);
/* System ROM (Assume 1MB) */
stage1_set_var_mtrr(1, 0xFFFFFFFF - (u32)((CONFIG_COREBOOT_ROMSIZE_KB << 10) - 1),
CONFIG_COREBOOT_ROMSIZE_KB << 10, MTRR_TYPE_WRTHROUGH);
/* 4GB - TOM2 */
msr = rdmsr(SYSCFG_MSR);
if (msr.lo & SYSCFG_MSR_TOM2En) {
msr = rdmsr(TOP_MEM2);
stage1_set_var_mtrr_x(2, 0x0, 0x00000001, msr.lo, msr.hi,
MTRR_TYPE_WRBACK);
}
/* Enable Fixed and Variable MTRRs MSRs*/
msr = rdmsr(SYSCFG_MSR);
msr.lo |= (SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn);
wrmsr(SYSCFG_MSR, msr);
/* Enable Fixed and Variable MTRRs */
msr = rdmsr(MTRRdefType_MSR);
msr.lo |= 0xC00;
wrmsr(MTRRdefType_MSR, msr);
enable_cache();
}
/* This function MUST be inlined as we can not use a stack -- CAR or real ram */
/* By yhlu 6.2005 */
/* Be warned, this function is used by both the BSP and APs to disable the
* fixed MTRRs used for CAR.
*/
inline __attribute__((always_inline)) void disable_cache_as_ram(void)
{
__asm__ volatile (
/* Disable the cache while we change MTRRs */
" movl %cr0, %eax \n"
" orl $(0x1<<30),%eax \n"
" movl %eax, %cr0 \n"
/* clear sth */
" movl $0x269, %ecx \n" /* fix4k_c8000 */
" xorl %edx, %edx \n"
" xorl %eax, %eax \n"
" wrmsr\n\t"
#if CONFIG_CARSIZE > 0x8000
" movl $0x268, %ecx \n" /* fix4k_c0000 */
" wrmsr \n"
#endif
/* disable fixed mtrr for now, it will be enabled by coreboot_ram again*/
" movl $0xC0010010, %ecx \n" /*SYSCFG_MSR */
" rdmsr \n"
" andl $(~(3<<18)), %eax \n" /*~(MtrrFixDramModEn | MtrrFixDramEn) */
" wrmsr \n"
/* Set the default memory type to UC, disable fixed MTRRs,
* and leave variable MTRRs enabled */
" movl $0x2ff, %ecx \n" /* $MTRRdefType_MSR */
" xorl %edx, %edx \n"
" movl $0x00000800, %eax \n"
" wrmsr \n"
/* enable cache */
" movl %cr0, %eax \n"
" andl $0x9fffffff,%eax \n"
" movl %eax, %cr0 \n"
);
}
/**
* Disable Cache As RAM (CAR) after memory is setup.
*
* Unknown how to do this just yet.
*/
void disable_car(void)
{
/* call the inlined function */
/* inlined function that disables the fixed MTRRs that
* are used for CAR stack space. The cache tags are still
* valid and the stack data is still in place. */
disable_cache_as_ram();
/* The BKDG says that a WBINVD will not flush CAR to RAM (because the
/* Now we need to get the cached data to RAM.
* The BKDG says that a WBINVD will not flush CAR to RAM (because the
* cache tags are not dirty).
* Solution:
* - Two subsequent memcpy in the same inline asm block, one from stack
* to backup, one from backup to stack.
* The solution for geode of using a inline asm memcpy of the stack
* The solution for Geode of using a inline asm memcpy of the stack
* onto itself will not mark the cache tags as dirty on K8.
*/
__asm__ __volatile__(
@ -71,8 +177,10 @@ void disable_car(void)
[carsizequads] "i" (CONFIG_CARSIZE/4)
: "memory", "%edi", "%esi", "%ecx");
banner(BIOS_DEBUG, "Disable_car: done wbinvd");
/* we're now running in ram. Although this will be called again, it does no harm to call it here. */
set_init_ram_access();
/* We're now running in ram.
* Setup the cache for normal operation. */
set_mtrr_ram_access();
banner(BIOS_DEBUG, "disable_car: done");
stage1_phase3();
}

View file

@ -246,27 +246,6 @@ void wait_ap_started(unsigned ap_apicid, void *gp)
}
}
/**
* disable cache as ram on a BSP.
* For reasons not totally known we are saving ecx and edx.
* That will work on k8 as we copy the stack and return in the same stack frame.
*/
void disable_cache_as_ram_bsp(void)
{
__asm__ volatile (
// "pushl %eax\n\t"
"pushl %edx\n\t"
"pushl %ecx\n\t"
);
disable_cache_as_ram();
__asm__ volatile (
"popl %ecx\n\t"
"popl %edx\n\t"
// "popl %eax\n\t"
);
}
/**
* wait for all apics to start. Make sure we don't wait on ourself.
@ -291,7 +270,7 @@ void wait_all_other_cores_started(unsigned bsp_apicid) // all aps other than cor
void STOP_CAR_AND_CPU(void)
{
disable_cache_as_ram(); // inline
stop_this_cpu(); // inline, it will stop all cores except node0/core0 the bsp ....
stop_this_cpu(); // inline
}
#ifndef MEM_TRAIN_SEQ
@ -470,13 +449,18 @@ cpu_init_detectedx = 0;
printk(BIOS_DEBUG, "while waiting for BSP signal to STOP, timeout in ap 0x%08x\n",
apicid);
}
/* indicate that we are in state 44 as well. We are catching up to the BSP. */
// old comment follows -- not sure what this means yet.
// bsp can not check it before stop_this_cpu
lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x44);
/* Now set up so we can use RAM. This will be low memory, i.e. BSP memory, already working. */
set_init_ram_access();
/* this is not done on Serengeti. */
/* Now set up so we can use RAM.
* This will be low memory, i.e. BSP memory, already working.
*/
/* Keep the ap's tom consistent with bsp's */
set_top_mem_ap(sysinfo->tom_k, sysinfo->tom2_k);
set_mtrr_ram_access();
/* This is not done on Serengeti. */
#if MEM_TRAIN_SEQ == 1
train_ram_on_node(id.nodeid, id.coreid, sysinfo,
(void *)STOP_CAR_AND_CPU);

View file

@ -40,23 +40,44 @@ void stage1_set_var_mtrr(
wrmsr(MTRRphysMask_MSR(reg), maskm);
}
void set_var_mtrr_x(
unsigned long reg, u32 base_lo, u32 base_hi, u32 size_lo, u32 size_hi, unsigned long type)
void stage1_set_var_mtrr_x(
unsigned long reg, u32 base_lo, u32 base_hi, u32 size_lo, u32 size_hi, unsigned long type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
struct msr basem, maskm;
basem.lo = (base_lo & 0xfffff000) | type;
basem.hi = base_hi & ((1<<(CPU_ADDR_BITS-32))-1);
wrmsr(MTRRphysBase_MSR(reg), basem);
maskm.hi = (1<<(CPU_ADDR_BITS-32))-1;
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
struct msr basem, maskm;
basem.lo = (base_lo & 0xfffff000) | type;
basem.hi = base_hi & ((1<<(CPU_ADDR_BITS-32))-1);
wrmsr(MTRRphysBase_MSR(reg), basem);
maskm.hi = (1<<(CPU_ADDR_BITS-32))-1;
if(size_lo) {
maskm.lo = ~(size_lo - 1) | 0x800;
maskm.lo = ~(size_lo - 1) | 0x800;
} else {
maskm.lo = 0x800;
maskm.hi &= ~(size_hi - 1);
}
wrmsr(MTRRphysMask_MSR(reg), maskm);
wrmsr(MTRRphysMask_MSR(reg), maskm);
}
/* Sets the entire fixed mtrr to a cache type. */
void stage1_set_fix_mtrr(u32 reg, u8 type)
{
struct msr msr;
/* Enable Modify Extended RdMem and WrMem settings */
msr = rdmsr(SYSCFG_MSR);
msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYSCFG_MSR, msr);
msr.lo = (type << 24) | (type << 16) | (type << 8) | type;
msr.hi = (type << 24) | (type << 16) | (type << 8) | type;
wrmsr(reg, msr);
/* Disable Modify Extended RdMem and WrMem settings */
msr = rdmsr(SYSCFG_MSR);
msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYSCFG_MSR, msr);
}
void cache_cbmem(int type)
@ -92,7 +113,7 @@ void do_early_mtrr_init(const unsigned long *mtrr_msrs)
wrmsr(msr_nr, msr);
}
#warning fix the XIP bits in stage1_mtrr.c that enable write through caching so we can do execute in place on the flash rom.
#warning fix the XIP bits in stage1_mtrr.c that enable write through caching so we can do execute in place on the flash rom.
#if 0
#if defined(XIP_ROM_SIZE)
/* enable write through caching so we can do execute in place

View file

@ -695,56 +695,9 @@ void showallroutes(int level, u32 dev);
/* k8/reset_test.c */
void distinguish_cpu_resets(unsigned nodeid);
/* These are functions that MUST be inlined as we can not use a stack -- CAR or real ram */
/* by yhlu 6.2005 */
/* be warned, this file will be used other cores and core 0 / node 0 */
static inline __attribute__((always_inline)) void disable_cache_as_ram(void)
{
__asm__ volatile (
/* We don't need cache as ram for now on */
/* disable cache */
"movl %cr0, %eax\n\t"
"orl $(0x1<<30),%eax\n\t"
"movl %eax, %cr0\n\t"
/* clear sth */
"movl $0x269, %ecx\n\t" /* fix4k_c8000*/
"xorl %edx, %edx\n\t"
"xorl %eax, %eax\n\t"
"wrmsr\n\t"
#if CONFIG_CARSIZE > 0x8000
"movl $0x268, %ecx\n\t" /* fix4k_c0000*/
"wrmsr\n\t"
#endif
/* disable fixed mtrr from now on, it will be enabled by coreboot_ram again*/
"movl $0xC0010010, %ecx\n\t"
// "movl $SYSCFG_MSR, %ecx\n\t"
"rdmsr\n\t"
"andl $(~(3<<18)), %eax\n\t"
// "andl $(~(SYSCFG_MSR_MtrrFixDramModEn | SYSCFG_MSR_MtrrFixDramEn)), %eax\n\t"
"wrmsr\n\t"
/* Set the default memory type and disable fixed and enable variable MTRRs */
"movl $0x2ff, %ecx\n\t"
// "movl $MTRRdefType_MSR, %ecx\n\t"
"xorl %edx, %edx\n\t"
/* Enable Variable and Disable Fixed MTRRs */
"movl $0x00000800, %eax\n\t"
"wrmsr\n\t"
/* enable cache */
"movl %cr0, %eax\n\t"
"andl $0x9fffffff,%eax\n\t"
"movl %eax, %cr0\n\t"
);
}
void disable_cache_as_ram_bsp(void);
inline __attribute__((always_inline)) void disable_cache_as_ram(void);
void set_top_mem_ap(unsigned tom_k, unsigned tom2_k);
#endif /* ! ASSEMBLY */
#endif /* AMD_K8_H */

View file

@ -267,7 +267,7 @@ static inline void clear_init_ram(void)
}
void set_init_ram_access(void);
void set_mtrr_ram_access(void);
void * bottom_of_stack(void);
EXPORT_SYMBOL(bottom_of_stack);

View file

@ -37,6 +37,10 @@ void x86_setup_mtrrs(unsigned address_bits);
int x86_mtrr_check(void);
void stage1_set_var_mtrr(unsigned long reg, unsigned long base,
unsigned long size, unsigned long type);
void stage1_set_fix_mtrr(u32 reg, u8 type);
void stage1_set_var_mtrr_x(unsigned long reg, u32 base_lo, u32 base_hi,
u32 size_lo, u32 size_hi, unsigned long type);
#endif