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:
parent
333cdb149f
commit
a794edb17b
6 changed files with 169 additions and 99 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue