Arthur Heymans has uploaded a new change for review. ( https://review.coreboot.org/19504 )
Change subject: lapic/apic_timer.c: Provide a tsc_freq_mhz for platforms using LAPIC_UDELAY ......................................................................
lapic/apic_timer.c: Provide a tsc_freq_mhz for platforms using LAPIC_UDELAY
This allows for more accurate timestamps.
Change-Id: Ic643681c3b9646bf7efbcd786c35a9beda9afc49 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/cpu/x86/lapic/apic_timer.c 1 file changed, 31 insertions(+), 19 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/04/19504/1
diff --git a/src/cpu/x86/lapic/apic_timer.c b/src/cpu/x86/lapic/apic_timer.c index cddc5ad..30a8ef3 100644 --- a/src/cpu/x86/lapic/apic_timer.c +++ b/src/cpu/x86/lapic/apic_timer.c @@ -22,6 +22,7 @@ #include <arch/cpu.h> #include <arch/early_variables.h> #include <cpu/x86/msr.h> +#include <cpu/x86/tsc.h> #include <cpu/x86/lapic.h> #include <cpu/intel/speedstep.h>
@@ -42,11 +43,11 @@ #else static u32 g_timer_fsb CAR_GLOBAL;
-static int set_timer_fsb(void) +static int get_fsb(void) { - struct cpuinfo_x86 c; + struct cpuinfo_x86 c; int core_fsb[8] = { -1, 133, -1, 166, -1, 100, -1, -1 }; - int core2_fsb[8] = { 266, 133, 200, 166, 333, 100, -1, -1 }; + int core2_fsb[8] = { 266, 133, 200, 166, 333, 100, 400, -1 }; int f2x_fsb[8] = { 100, 133, 200, 166, -1, -1, -1, -1 };
get_fms(&c, cpuid_eax(1)); @@ -55,42 +56,53 @@ switch (c.x86_model) { case 0xe: /* Core Solo/Duo */ case 0x1c: /* Atom */ - car_set_var(g_timer_fsb, - core_fsb[rdmsr(MSR_FSB_FREQ).lo & 7]); - return 0; + return core_fsb[rdmsr(MSR_FSB_FREQ).lo & 7]; case 0xf: /* Core 2 or Xeon */ case 0x17: /* Enhanced Core */ - car_set_var(g_timer_fsb, - core2_fsb[rdmsr(MSR_FSB_FREQ).lo & 7]); - return 0; + return core2_fsb[rdmsr(MSR_FSB_FREQ).lo & 7]; case 0x2a: /* SandyBridge BCLK fixed at 100MHz*/ case 0x3a: /* IvyBridge BCLK fixed at 100MHz*/ case 0x3c: /* Haswell BCLK fixed at 100MHz */ case 0x45: /* Haswell-ULT BCLK fixed at 100MHz */ - car_set_var(g_timer_fsb, 100); - return 0; + return 100; default: - car_set_var(g_timer_fsb, 200); - return 0; + return 200; } case 0xf: /* Netburst */ switch (c.x86_model) { case 0x2: - car_set_var(g_timer_fsb, - f2x_fsb[(rdmsr(0x2c).lo >> 16) & 7]); - return 0; + return f2x_fsb[(rdmsr(0x2c).lo >> 16) & 7]; case 0x3: case 0x4: case 0x6: - car_set_var(g_timer_fsb, - core2_fsb[(rdmsr(0x2c).lo >> 16) & 7]); - return 0; + return core2_fsb[(rdmsr(0x2c).lo >> 16) & 7]; } /* default: fallthrough */ default: return -1; } }
+unsigned long tsc_freq_mhz(void) +{ + msr_t msr; + unsigned long divisor; + + msr = rdmsr(IA32_PERF_STS); + divisor = (msr.hi >> 8) & 0x1f; + return get_fsb() * divisor; +} + +static int set_timer_fsb(void) +{ + int fsb = get_fsb(); + if (fsb > 0) { + car_set_var(g_timer_fsb, get_fsb()); + return 0; + } else { + return 1; + } +} + static inline u32 get_timer_fsb(void) { return car_get_var(g_timer_fsb);