Author: mjones Date: 2009-02-10 23:40:10 +0100 (Tue, 10 Feb 2009) New Revision: 1128
Modified: coreboot-v3/arch/x86/amd/k8/stage1.c coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c coreboot-v3/arch/x86/stage1_mtrr.c coreboot-v3/include/arch/x86/amd/k8/k8.h coreboot-v3/include/arch/x86/cpu.h coreboot-v3/include/arch/x86/mtrr.h Log: 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
Modified: coreboot-v3/arch/x86/amd/k8/stage1.c =================================================================== --- coreboot-v3/arch/x86/amd/k8/stage1.c 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/arch/x86/amd/k8/stage1.c 2009-02-10 22:40:10 UTC (rev 1128) @@ -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 @@ [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(); }
Modified: coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c =================================================================== --- coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2009-02-10 22:40:10 UTC (rev 1128) @@ -246,28 +246,7 @@ } }
-/** - * 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. * @param bsp_apicid The BSP APIC ID @@ -291,7 +270,7 @@ 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 @@ 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);
Modified: coreboot-v3/arch/x86/stage1_mtrr.c =================================================================== --- coreboot-v3/arch/x86/stage1_mtrr.c 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/arch/x86/stage1_mtrr.c 2009-02-10 22:40:10 UTC (rev 1128) @@ -40,25 +40,46 @@ 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) { /* Enable caching for 0 - 1MB using variable mtrr */ @@ -92,7 +113,7 @@ 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
Modified: coreboot-v3/include/arch/x86/amd/k8/k8.h =================================================================== --- coreboot-v3/include/arch/x86/amd/k8/k8.h 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/include/arch/x86/amd/k8/k8.h 2009-02-10 22:40:10 UTC (rev 1128) @@ -695,56 +695,9 @@ /* 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) -{ +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); - +void set_top_mem_ap(unsigned tom_k, unsigned tom2_k); #endif /* ! ASSEMBLY */
#endif /* AMD_K8_H */
Modified: coreboot-v3/include/arch/x86/cpu.h =================================================================== --- coreboot-v3/include/arch/x86/cpu.h 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/include/arch/x86/cpu.h 2009-02-10 22:40:10 UTC (rev 1128) @@ -267,7 +267,7 @@
}
-void set_init_ram_access(void); +void set_mtrr_ram_access(void);
void * bottom_of_stack(void); EXPORT_SYMBOL(bottom_of_stack);
Modified: coreboot-v3/include/arch/x86/mtrr.h =================================================================== --- coreboot-v3/include/arch/x86/mtrr.h 2009-02-10 22:35:49 UTC (rev 1127) +++ coreboot-v3/include/arch/x86/mtrr.h 2009-02-10 22:40:10 UTC (rev 1128) @@ -37,7 +37,11 @@ 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
#endif /* ARCH_X86_MTRR_H */