added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64' old head: 7444a55ce55af4fecf298a1749c1c23228305385 new head: 5c7d52183c2182761151ba2f8f72bb7b39e50053 ---------------------------------------------------------------------------- 5c7d521: Implemented system_time() for x86_64. * Uses 64-bit multiplication, special handling for CPUs clocked < 1 GHz in system_time_nsecs() not required like on x86. * Tested against a straight conversion of the x86 version, noticably faster with a large number of system_time() calls. [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: 5c7d52183c2182761151ba2f8f72bb7b39e50053 Author: Alex Smith <alex@xxxxxxxxxxxxxxxx> Date: Sun Jul 8 09:16:44 2012 UTC ---------------------------------------------------------------------------- 3 files changed, 47 insertions(+), 113 deletions(-) headers/private/kernel/arch/x86/arch_cpu.h | 7 +- src/system/kernel/arch/x86/arch_cpu.cpp | 7 + .../libroot/os/arch/x86_64/system_time_asm.S | 146 ++++------------ ---------------------------------------------------------------------------- diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index f688a20..204c901 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -367,9 +367,14 @@ extern "C" { struct arch_thread; - +#ifdef __x86_64__ +void __x86_setup_system_time(uint64 conversionFactor, + uint64 conversionFactorNsecs); +#else void __x86_setup_system_time(uint32 conversionFactor, uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); +#endif + void x86_context_switch(struct arch_thread* oldState, struct arch_thread* newState); void x86_userspace_thread_exit(void); diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index a618504..6a7a206 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -820,6 +820,12 @@ arch_cpu_init(kernel_args* args) uint32 conversionFactor = args->arch_args.system_time_cv_factor; uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000; +#ifdef __x86_64__ + // The x86_64 system_time() implementation uses 64-bit multiplication and + // therefore shifting is not necessary for low frequencies (it's also not + // too likely that there'll be any x86_64 CPUs clocked under 1GHz). + __x86_setup_system_time(conversionFactor, conversionFactorNsecs); +#else if (conversionFactorNsecs >> 32 != 0) { // the TSC frequency is < 1 GHz, which forces us to shift the factor __x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16, @@ -828,6 +834,7 @@ arch_cpu_init(kernel_args* args) // the TSC frequency is >= 1 GHz __x86_setup_system_time(conversionFactor, conversionFactorNsecs, false); } +#endif return B_OK; } diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S index d6df8fa..f63bdf3 100644 --- a/src/system/libroot/os/arch/x86_64/system_time_asm.S +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -7,143 +7,65 @@ * Distributed under the terms of the NewOS License. */ -#include <asm_defs.h> - -FUNCTION(__x86_setup_system_time): - ret -FUNCTION_END(__x86_setup_system_time) - -// TODO: Implement these. - -/* int64 system_time(); */ -FUNCTION(system_time): - ud2a - ret -FUNCTION_END(system_time) +#include <asm_defs.h> -/* int64 system_time_nsecs(); */ -FUNCTION(system_time_nsecs): - ud2a - ret -FUNCTION_END(system_time_nsecs) -#if 0 /* saves the conversion factor needed for system_time */ -.lcomm cv_factor 4 -.lcomm cv_factor_nsecs 4 -.lcomm cv_factor_nsecs_shift 1 +.lcomm cv_factor 8 +.lcomm cv_factor_nsecs 8 .text FUNCTION(__x86_setup_system_time): - movl 4(%esp), %eax - movl %eax, cv_factor - movl 8(%esp), %eax - movl %eax, cv_factor_nsecs - movb 12(%esp), %al - movb %al, cv_factor_nsecs_shift + movq %rdi, cv_factor + movq %rsi, cv_factor_nsecs ret FUNCTION_END(__x86_setup_system_time) /* int64 system_time(); */ FUNCTION(system_time): - pushl %ebx - pushl %ecx - movl cv_factor, %ebx - - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ - - movl %edx, %ecx /* save high half */ - mull %ebx /* truncate %eax, but keep %edx */ - movl %ecx, %eax - movl %edx, %ecx /* save high half of low */ - mull %ebx /*, %eax*/ - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - subl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx - popl %ecx - popl %ebx - ret -FUNCTION_END(system_time) - - -/* int64 system_time_nsecs(); */ -FUNCTION(system_time_nsecs): - testb $0, cv_factor_nsecs_shift - jne 1f - - /* same algorithm as system_time(), just with a different factor */ - - pushl %ebx - pushl %ecx - movl cv_factor_nsecs, %ebx - - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ - - movl %edx, %ecx /* save high half */ - mull %ebx /* truncate %eax, but keep %edx */ - movl %ecx, %eax - movl %edx, %ecx /* save high half of low */ - mull %ebx /*, %eax*/ - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - subl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx - popl %ecx - popl %ebx - ret + movq cv_factor, %rcx -1: - /* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */ + // Load 64-bit TSC into %eax (low), %edx (high). + rdtsc - pushl %ebx - pushl %ecx - pushl %esi - movl cv_factor_nsecs, %ebx + // Convert into a single 64-bit value. + shl $32, %rdx + orq %rdx, %rax - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ + // Multiply by conversion factor, result in %rax (low), %rdx (high). + mulq %rcx - /* save high half */ - movl %edx, %ecx - - /* multiply low half by conversion factor */ - mull %ebx + // Shift the result right by 32 bits. + shr $32, %rax + shl $32, %rdx + orq %rdx, %rax + ret +FUNCTION_END(system_time) - /* save result */ - movl %eax, %esi /* low half -> %esi */ - movl %ecx, %eax - movl %edx, %ecx /* high half -> %ecx */ - /* multiply high half by conversion factor */ - mull %ebx +/* int64 system_time_nsecs(); */ +FUNCTION(system_time_nsecs): + // Same algorithm as system_time(), just with a different factor. + movq cv_factor_nsecs, %rcx - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - xorl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx + // Load 64-bit TSC into %eax (low), %edx (high). + rdtsc - /* shift the result left 16 bit */ - shl $16, %edx - movl %eax, %ebx - shr $16, %ebx - orw %bx, %dx - shl $16, %eax + // Convert into a single 64-bit value. + shl $32, %rdx + orq %rdx, %rax - /* add the high 16 bit of the low half of the low product */ - shr $16, %esi - orw %si, %ax + // Multiply by conversion factor, result in %rax (low), %rdx (high). + mulq %rcx - popl %esi - popl %ecx - popl %ebx + // Shift the result right by 32 bits. + shr $32, %rax + shl $32, %rdx + orq %rdx, %rax ret FUNCTION_END(system_time_nsecs) -#endif