From 8b3b05cbf9cfc334c4abc5dc22d4706d36b93115 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 21 Apr 2009 00:38:11 +0000 Subject: [PATCH] Synchronize the TSCs of all CPUs early in the boot process, so system_time() will return consistent values. This helps with debug measurements for the time being. Obviously we'll have to think of something different when we support speed-stepping on models with frequency-dependent TSCs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30287 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/arch_cpu.h | 1 + src/system/kernel/arch/x86/arch_cpu.cpp | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index ac40cca3b8..5b34644279 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -22,6 +22,7 @@ // MSR registers (possibly Intel specific) +#define IA32_MSR_TSC 0x10 #define IA32_MSR_APIC_BASE 0x1b #define IA32_MSR_MTRR_CAPABILITIES 0xfe diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 34d7b69b12..82a682b6cb 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -78,6 +78,7 @@ bool gHasSSE = false; static uint32 sCpuRendezvous; static uint32 sCpuRendezvous2; +static vint32 sTSCSyncRendezvous; segment_descriptor *gGDT = NULL; @@ -501,6 +502,28 @@ arch_cpu_preboot_init_percpu(kernel_args *args, int cpu) x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); gX86SwapFPUFunc = i386_fnsave_swap; + // On SMP system we want to synchronize the CPUs' TSCs, so system_time() + // will return consistent values. + if (smp_get_num_cpus() > 1) { + // let the first CPU prepare the rendezvous point + if (cpu == 0) + sTSCSyncRendezvous = smp_get_num_cpus() - 1; + + // One CPU after the other will drop out of this loop and be caught by + // the loop below, until the last CPU (0) gets there. Save for +/- a few + // cycles the CPUs should pass the second loop at the same time. + while (sTSCSyncRendezvous > cpu) { + } + + sTSCSyncRendezvous = cpu - 1; + + while (sTSCSyncRendezvous != -1) { + } + + // reset TSC to 0 + x86_write_msr(IA32_MSR_TSC, 0); + } + return B_OK; }