From 0122afb6093849102caa9662ac14380a41cfb094 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 30 Jul 2015 14:07:15 -0500 Subject: cpu/amd/fam10h-fam15h: Update Fam15h APIC config and startup sequence This fixes Family 15h multiple package support; the previous code hung in CAR setup and romstage when more than one CPU package was installed for a variety of loosely related reasons. TEST: Booted ASUS KGPE-D16 with two Opteron 6328 processors and several different RDIMM configurations. Change-Id: I171197c90f72d3496a385465937b7666cbf7e308 Signed-off-by: Timothy Pearson Reviewed-on: http://review.coreboot.org/12020 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc --- src/cpu/amd/family_10h-family_15h/fidvid.c | 81 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 40 deletions(-) (limited to 'src/cpu/amd/family_10h-family_15h/fidvid.c') diff --git a/src/cpu/amd/family_10h-family_15h/fidvid.c b/src/cpu/amd/family_10h-family_15h/fidvid.c index 3af18bd06b..8a006cbbb3 100644 --- a/src/cpu/amd/family_10h-family_15h/fidvid.c +++ b/src/cpu/amd/family_10h-family_15h/fidvid.c @@ -629,44 +629,45 @@ static void prep_fid_change(void) } static void waitCurrentPstate(u32 target_pstate) { - msr_t initial_msr = rdmsr(TSC_MSR); - msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR); - msr_t tsc_msr; - u8 timedout ; - - /* paranoia ? I fear when we run fixPsNbVidBeforeWR we can enter a - * P1 that is a copy of P0, therefore has the same NB DID but the - * TSC will count twice per tick, so we have to wait for twice the - * count to achieve the desired timeout. But I'm likely to - * misunderstand this... - */ - u32 corrected_timeout = ( (pstate_msr.lo==1) - && (!(rdmsr(0xC0010065).lo & NB_DID_M_ON)) ) ? - WAIT_PSTATE_TIMEOUT*2 : WAIT_PSTATE_TIMEOUT ; - msr_t timeout; - - timeout.lo = initial_msr.lo + corrected_timeout ; - timeout.hi = initial_msr.hi; - if ( (((u32)0xffffffff) - initial_msr.lo) < corrected_timeout ) { - timeout.hi++; - } - - // assuming TSC ticks at 1.25 ns per tick (800 MHz) - do { - pstate_msr = rdmsr(CUR_PSTATE_MSR); - tsc_msr = rdmsr(TSC_MSR); - timedout = (tsc_msr.hi > timeout.hi) - || ((tsc_msr.hi == timeout.hi) && (tsc_msr.lo > timeout.lo )); - } while ( (pstate_msr.lo != target_pstate) && (! timedout) ) ; - - if (pstate_msr.lo != target_pstate) { - msr_t limit_msr = rdmsr(0xc0010061); - printk(BIOS_ERR, "*** Time out waiting for P-state %01x. Current P-state %01x P-state current limit MSRC001_0061=%08x %08x\n", target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo); - - do { // should we just go on instead ? - pstate_msr = rdmsr(CUR_PSTATE_MSR); - } while ( pstate_msr.lo != target_pstate ) ; - } + msr_t initial_msr = rdmsr(TSC_MSR); + msr_t pstate_msr = rdmsr(CUR_PSTATE_MSR); + msr_t tsc_msr; + u8 timedout ; + + /* paranoia ? I fear when we run fixPsNbVidBeforeWR we can enter a + * P1 that is a copy of P0, therefore has the same NB DID but the + * TSC will count twice per tick, so we have to wait for twice the + * count to achieve the desired timeout. But I'm likely to + * misunderstand this... + */ + u32 corrected_timeout = ((pstate_msr.lo==1) + && (!(rdmsr(0xC0010065).lo & NB_DID_M_ON)) ) ? + WAIT_PSTATE_TIMEOUT*2 : WAIT_PSTATE_TIMEOUT; + msr_t timeout; + + timeout.lo = initial_msr.lo + corrected_timeout ; + timeout.hi = initial_msr.hi; + if ( (((u32)0xffffffff) - initial_msr.lo) < corrected_timeout ) { + timeout.hi++; + } + + // assuming TSC ticks at 1.25 ns per tick (800 MHz) + do { + pstate_msr = rdmsr(CUR_PSTATE_MSR); + tsc_msr = rdmsr(TSC_MSR); + timedout = (tsc_msr.hi > timeout.hi) + || ((tsc_msr.hi == timeout.hi) && (tsc_msr.lo > timeout.lo )); + } while ( (pstate_msr.lo != target_pstate) && (! timedout) ) ; + + if (pstate_msr.lo != target_pstate) { + msr_t limit_msr = rdmsr(0xc0010061); + printk(BIOS_ERR, "*** APIC ID %02x: timed out waiting for P-state %01x. Current P-state %01x P-state current limit MSRC001_0061=%08x %08x\n", + cpuid_ebx(0x00000001) >> 24, target_pstate, pstate_msr.lo, limit_msr.hi, limit_msr.lo); + + do { // should we just go on instead ? + pstate_msr = rdmsr(CUR_PSTATE_MSR); + } while ( pstate_msr.lo != target_pstate ) ; + } } static void set_pstate(u32 nonBoostedPState) { @@ -1060,13 +1061,13 @@ static int init_fidvid_bsp(u32 bsp_apicid, u32 nodes) APs and BSP */ ap_apicidx.num = 0; - for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE_RANGE, store_ap_apicid, &ap_apicidx); + for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE_RANGE, -1, store_ap_apicid, &ap_apicidx); for (i = 0; i < ap_apicidx.num; i++) { init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv); } #else - for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage1, &fv); + for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, -1, init_fidvid_bsp_stage1, &fv); #endif print_debug_fv("common_fid = ", fv.common_fid); -- cgit v1.2.3