From 730a043fb6cb4dd3cb5af8f8640365727b598648 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 16 Oct 2015 13:51:51 -0500 Subject: cpu/amd: Add initial AMD Family 15h support TEST: Booted ASUS KGPE-D16 with single Opteron 6380 * Unbuffered DDR3 DIMMs tested and working * Suspend to RAM (S3) tested and working Change-Id: Idffd2ce36ce183fbfa087e5ba69a9148f084b45e Signed-off-by: Timothy Pearson Reviewed-on: http://review.coreboot.org/11966 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/cpu/amd/car/cache_as_ram.inc | 130 ++++++++++++++++++++++++++++++--- src/cpu/amd/car/disable_cache_as_ram.c | 89 +++++++++++++++++----- src/cpu/amd/car/post_cache_as_ram.c | 16 ++-- 3 files changed, 197 insertions(+), 38 deletions(-) (limited to 'src/cpu/amd/car') diff --git a/src/cpu/amd/car/cache_as_ram.inc b/src/cpu/amd/car/cache_as_ram.inc index 8fe91a0147..9874ec47a2 100644 --- a/src/cpu/amd/car/cache_as_ram.inc +++ b/src/cpu/amd/car/cache_as_ram.inc @@ -28,19 +28,24 @@ #define CacheSizeAPStack CONFIG_DCACHE_AP_STACK_SIZE #define MSR_MCFG_BASE 0xC0010058 -#define MSR_FAM10 0xC001102A +#define MSR_BU_CFG2 0xC001102A #define jmp_if_not_k8(x) comisd %xmm2, %xmm1; jae x #define jmp_if_k8(x) comisd %xmm2, %xmm1; jb x +#define jmp_if_not_fam15h(x) comisd %xmm3, %xmm1; jb x +#define jmp_if_fam15h(x) comisd %xmm3, %xmm1; jae x #define CPUID_MASK 0x0ff00f00 #define CPUID_VAL_FAM10_ROTATED 0x0f000010 +#define CPUID_VAL_FAM15_ROTATED 0x0f000060 /* * XMM map: * xmm1: CPU family * xmm2: Fam10h comparison value - * xmm3: Backup EBX + * xmm3: Fam15h comparison value + * xmm4: Backup EBX + * xmm5: Coreboot init detect */ /* Save the BIST result. */ @@ -60,7 +65,7 @@ cache_as_ram_setup: movl %eax, %cr4 /* Figure out the CPU family. */ - cvtsi2sd %ebx, %xmm3 + cvtsi2sd %ebx, %xmm4 movl $0x01, %eax cpuid /* Base family is bits 8..11, extended family is bits 20..27. */ @@ -70,13 +75,16 @@ cache_as_ram_setup: cvtsi2sd %eax, %xmm1 movl $CPUID_VAL_FAM10_ROTATED, %eax cvtsi2sd %eax, %xmm2 - cvtsd2si %xmm3, %ebx + movl $CPUID_VAL_FAM15_ROTATED, %eax + cvtsi2sd %eax, %xmm3 + cvtsd2si %xmm4, %ebx /* Check if cpu_init_detected. */ movl $MTRR_DEF_TYPE_MSR, %ecx rdmsr andl $MTRR_DEF_TYPE_EN, %eax movl %eax, %ebx /* We store the status. */ + cvtsi2sd %ebx, %xmm5 jmp_if_k8(CAR_FAM10_out_post_errata) @@ -117,21 +125,24 @@ cache_as_ram_setup: CAR_FAM10_out: + jmp_if_fam15h(CAR_FAM10_errata_applied) /* * Errata 193: Disable clean copybacks to L3 cache to allow cached ROM. * Re-enable it in after RAM is initialized and before CAR is disabled. */ - movl $MSR_FAM10, %ecx + movl $MSR_BU_CFG2, %ecx rdmsr - bts $15, %eax + bts $15, %eax /* Set bit 15 in EDX:EAX (bit 15 in EAX). */ wrmsr /* Erratum 343, RevGuide for Fam10h, Pub#41322 Rev. 3.33 */ - movl $MSR_FAM10, %ecx + movl $MSR_BU_CFG2, %ecx rdmsr bts $35-32, %edx /* Set bit 35 in EDX:EAX (bit 3 in EDX). */ wrmsr +CAR_FAM10_errata_applied: + #if CONFIG_MMCONF_SUPPORT #if (CONFIG_MMCONF_BASE_ADDRESS > 0xFFFFFFFF) #error "MMCONF_BASE_ADDRESS too big" @@ -166,6 +177,63 @@ CAR_FAM10_out: CAR_FAM10_out_post_errata: + /* Fam15h APIC IDs do not depend on NB config bit 54 */ + jmp_if_not_fam15h(skip_nb54_set) + movl $0xc001001f, %ecx /* NB_CFG_MSR */ + rdmsr + bts $(54 - 32), %edx /* Set NB config bit 54 */ + wrmsr + +skip_nb54_set: + /* On Fam15h CPUs each compute unit's MTRRs are shared between two cores */ + jmp_if_not_fam15h(skip_cu_check) + + /* Get the initial APIC ID. */ + movl $1, %eax + cpuid + movl %ebx, %eax + + /* Restore init detect */ + cvtsd2si %xmm5, %ebx + + /* Determine if this is the second core to start in a compute unit; if so, wait for first core start, clear init detect and skip MTRR init */ + bt $24, %eax + jnc skip_cu_check /* First core in the compute unit jumps to skip_cu_check */ + + /* Determine if this is the second core to start in a compute unit; if so, clear init detect and skip MTRR init */ + /* Busywait until the first core sets up the MTRRs */ +check_init_detect_1: + /* Check if cpu_init_detected. */ + movl $MTRR_DEF_TYPE_MSR, %ecx + rdmsr + andl $MTRR_DEF_TYPE_EN, %eax + cmp $0x00000000, %eax + je check_init_detect_1 /* First core has not yet started */ + +check_init_detect_2: + movl $SYSCFG_MSR, %ecx + rdmsr + andl $(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrVarDramEn), %eax + cmp $0x00000000, %eax + je check_init_detect_2 /* First core has not yet started */ + + /* First core has now started */ + movl $0x00000000, %ebx /* Clear init detect flag */ + cvtsi2sd %ebx, %xmm5 + jmp fam10_mtrr_setup_complete + +skip_cu_check: + + jmp_if_not_fam15h(CAR_FAM15_errata_applied) + + /* Erratum 714, RevGuide for Fam15h, Pub#48063 Rev. 3.24 */ + movl $MSR_BU_CFG2, %ecx + rdmsr + bts $8, %eax /* Set bit 8 in EDX:EAX (bit 8 in EAX). */ + wrmsr + +CAR_FAM15_errata_applied: + /* Set MtrrFixDramModEn for clear fixed MTRR. */ enable_fixed_mtrr_dram_modify: movl $SYSCFG_MSR, %ecx @@ -334,8 +402,42 @@ wbcache_post_fam10_setup: orl $(SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn), %eax wrmsr +fam10_mtrr_setup_complete: post_code(0xa1) + /* Disable conversion of INVD to WBINVD (INVDWBINVD = 0) */ + mov $0xc0010015, %ecx + rdmsr + btr $4, %eax + wrmsr + +jmp_if_not_fam15h(fam15_car_msr_setup_complete) + /* Disable streaming store (DisSS = 1) */ + mov $0xc0011020, %ecx + rdmsr + bts $28, %eax + wrmsr + + /* Disable speculative ITLB reloads (DisSpecTlbRld = 1) */ + mov $0xc0011021, %ecx + rdmsr + bts $9, %eax + wrmsr + + /* Disable speculative DTLB reloads (DisSpecTlbRld = 1) and set DisHwPf = 1 */ + mov $0xc0011022, %ecx + rdmsr + bts $4, %eax + bts $13, %eax + wrmsr + + /* Disable CR0 combining (CombineCr0Cd = 0) */ + mov $0xc001102b, %ecx + rdmsr + btr $49-32, %edx + wrmsr +fam15_car_msr_setup_complete: + /* Enable cache. */ movl %cr0, %eax andl $(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax @@ -416,9 +518,6 @@ CAR_FAM10_ap: * to reverse it. */ - /* Store our init detected. */ - movl %ebx, %esi - /* Get the coreid bits at first. */ movl $0x80000008, %eax cpuid @@ -437,6 +536,8 @@ CAR_FAM10_ap: movl %edi, %ecx /* CoreID bits */ bt $(54 - 32), %edx jc roll_cfg + + /* Fam10h NB config bit 54 was not set */ rolb %cl, %bl roll_cfg: @@ -446,8 +547,8 @@ roll_cfg: movl $(CacheBase + (CacheSize - (CacheSizeBSPStack + CacheSizeBSPSlush))), %esp subl %eax, %esp - /* Retrive init detected. */ - movl %esi, %ebx + /* Restore init detect */ + cvtsd2si %xmm5, %ebx post_code(0xa4) @@ -460,6 +561,8 @@ CAR_FAM10_ap_out: andl $~(3 << 9), %eax movl %eax, %cr4 + post_code(0xa6) + /* Restore the BIST result. */ movl %ebp, %eax @@ -467,6 +570,9 @@ CAR_FAM10_ap_out: movl %esp, %ebp pushl %ebx /* Init detected. */ pushl %eax /* BIST */ + + post_code(0xa7) + call cache_as_ram_main /* We will not go back. */ diff --git a/src/cpu/amd/car/disable_cache_as_ram.c b/src/cpu/amd/car/disable_cache_as_ram.c index ae295d33ee..e8d5af8047 100644 --- a/src/cpu/amd/car/disable_cache_as_ram.c +++ b/src/cpu/amd/car/disable_cache_as_ram.c @@ -15,46 +15,95 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * be warned, this file will be used other cores and core 0 / node 0 + * WARNING: this file will be used by both any AP cores and core 0 / node 0 */ #include -static inline __attribute__((always_inline)) void disable_cache_as_ram(void) +static inline __attribute__((always_inline)) uint32_t amd_fam1x_cpu_family(void) +{ + uint32_t family; + + family = cpuid_eax(0x80000001); + family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); + + return family; +} + +static inline __attribute__((always_inline)) void disable_cache_as_ram(uint8_t skip_sharedc_config) { msr_t msr; + uint32_t family; - /* disable cache */ - write_cr0(read_cr0() | CR0_CacheDisable); + if (!skip_sharedc_config) { + /* disable cache */ + write_cr0(read_cr0() | CR0_CacheDisable); - msr.lo = 0; - msr.hi = 0; - wrmsr(MTRR_FIX_4K_C8000, msr); + msr.lo = 0; + msr.hi = 0; + wrmsr(MTRR_FIX_4K_C8000, msr); #if CONFIG_DCACHE_RAM_SIZE > 0x8000 - wrmsr(MTRR_FIX_4K_C0000, msr); + wrmsr(MTRR_FIX_4K_C0000, msr); #endif #if CONFIG_DCACHE_RAM_SIZE > 0x10000 - wrmsr(MTRR_FIX_4K_D0000, msr); + wrmsr(MTRR_FIX_4K_D0000, msr); #endif #if CONFIG_DCACHE_RAM_SIZE > 0x18000 - wrmsr(MTRR_FIX_4K_D8000, msr); + wrmsr(MTRR_FIX_4K_D8000, msr); #endif - /* disable fixed mtrr from now on, it will be enabled by ramstage again*/ + /* disable fixed mtrr from now on, it will be enabled by ramstage again */ + msr = rdmsr(SYSCFG_MSR); + msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn); + wrmsr(SYSCFG_MSR, msr); + + /* Set the default memory type and disable fixed and enable variable MTRRs */ + msr.hi = 0; + msr.lo = (1 << 11); - msr = rdmsr(SYSCFG_MSR); - msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn); - wrmsr(SYSCFG_MSR, msr); + wrmsr(MTRR_DEF_TYPE_MSR, msr); - /* Set the default memory type and disable fixed and enable variable MTRRs */ - msr.hi = 0; - msr.lo = (1 << 11); + enable_cache(); + } - wrmsr(MTRR_DEF_TYPE_MSR, msr); + /* INVDWBINVD = 1 */ + msr = rdmsr(0xc0010015); + msr.lo |= (0x1 << 4); + wrmsr(0xc0010015, msr); - enable_cache(); + family = amd_fam1x_cpu_family(); + +#if IS_ENABLED(CPU_AMD_MODEL_10XXX) + if (family >= 0x6f) { + /* Family 15h or later */ + + /* DisSS = 0 */ + msr = rdmsr(0xc0011020); + msr.lo &= ~(0x1 << 28); + wrmsr(0xc0011020, msr); + + if (!skip_sharedc_config) { + /* DisSpecTlbRld = 0 */ + msr = rdmsr(0xc0011021); + msr.lo &= ~(0x1 << 9); + wrmsr(0xc0011021, msr); + + /* Erratum 714: SpecNbReqDis = 0 */ + msr = rdmsr(BU_CFG2_MSR); + msr.lo &= ~(0x1 << 8); + wrmsr(BU_CFG2_MSR, msr); + } + + /* DisSpecTlbRld = 0 */ + /* DisHwPf = 0 */ + msr = rdmsr(0xc0011022); + msr.lo &= ~(0x1 << 4); + msr.lo &= ~(0x1 << 13); + wrmsr(0xc0011022, msr); + } +#endif } static void disable_cache_as_ram_bsp(void) { - disable_cache_as_ram(); + disable_cache_as_ram(0); } diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c index 61d47a2ed9..49b9ee3fe3 100644 --- a/src/cpu/amd/car/post_cache_as_ram.c +++ b/src/cpu/amd/car/post_cache_as_ram.c @@ -84,18 +84,19 @@ static void prepare_ramstage_region(void *resume_backup_memory) static void vErrata343(void) { #ifdef BU_CFG2_MSR - msr_t msr; - unsigned int uiMask = 0xFFFFFFF7; + msr_t msr; + unsigned int uiMask = 0xFFFFFFF7; - msr = rdmsr(BU_CFG2_MSR); - msr.hi &= uiMask; // set bit 35 to 0 - wrmsr(BU_CFG2_MSR, msr); + msr = rdmsr(BU_CFG2_MSR); + msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0 + wrmsr(BU_CFG2_MSR, msr); #endif } void post_cache_as_ram(void) { void *resume_backup_memory = NULL; + uint32_t family = amd_fam1x_cpu_family(); struct romstage_handoff *handoff; handoff = romstage_handoff_find_or_add(); @@ -112,7 +113,10 @@ void post_cache_as_ram(void) prepare_romstage_ramstack(resume_backup_memory); /* from here don't store more data in CAR */ - vErrata343(); + if (family < 0x6f) { + /* Family 10h or earlier */ + vErrata343(); + } size_t car_size = car_data_size(); void *migrated_car = (void *)(CONFIG_RAMTOP - car_size); -- cgit v1.2.3