diff options
author | Michael Brown <mcb30@ipxe.org> | 2017-01-25 20:59:15 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2017-01-26 08:17:37 +0000 |
commit | 302f1eeb80706fb10067efedb1279fa3f85ddda2 (patch) | |
tree | 90e58309094b20a26cedc8244fabf72d96fe6135 /src/arch/x86/include | |
parent | d37e025b81cb6fd0e7833b927ed138b42a628bc8 (diff) | |
download | ipxe-302f1eeb80706fb10067efedb1279fa3f85ddda2.tar.gz |
[time] Allow timer to be selected at runtime
Allow the active timer (providing udelay() and currticks()) to be
selected at runtime based on probing during the INIT_EARLY stage of
initialisation.
TICKS_PER_SEC is now a fixed compile-time constant for all builds, and
is independent of the underlying clock tick rate. We choose the value
1024 to allow multiplications and divisions on seconds to be converted
to bit shifts.
TICKS_PER_MS is defined as 1, allowing multiplications and divisions
on milliseconds to be omitted entirely. The 2% inaccuracy in this
definition is negligible when using the standard BIOS timer (running
at around 18.2Hz).
TIMER_RDTSC now checks for a constant TSC before claiming to be a
usable timer. (This timer can be tested in KVM via the command-line
option "-cpu host,+invtsc".)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/x86/include')
-rw-r--r-- | src/arch/x86/include/bios.h | 2 | ||||
-rw-r--r-- | src/arch/x86/include/bits/errfile.h | 1 | ||||
-rw-r--r-- | src/arch/x86/include/bits/timer.h | 15 | ||||
-rw-r--r-- | src/arch/x86/include/ipxe/bios_timer.h | 44 | ||||
-rw-r--r-- | src/arch/x86/include/ipxe/cpuid.h | 6 | ||||
-rw-r--r-- | src/arch/x86/include/ipxe/rdtsc_timer.h | 39 |
6 files changed, 9 insertions, 98 deletions
diff --git a/src/arch/x86/include/bios.h b/src/arch/x86/include/bios.h index a5a5d887c..14e7acbc7 100644 --- a/src/arch/x86/include/bios.h +++ b/src/arch/x86/include/bios.h @@ -7,6 +7,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define BDA_EBDA 0x000e #define BDA_EQUIPMENT_WORD 0x0010 #define BDA_FBMS 0x0013 +#define BDA_TICKS 0x006c +#define BDA_MIDNIGHT 0x0070 #define BDA_REBOOT 0x0072 #define BDA_REBOOT_WARM 0x1234 #define BDA_NUM_DRIVES 0x0075 diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index 105cdf5d2..9d1fed7f6 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_rtc_entropy ( ERRFILE_ARCH | ERRFILE_CORE | 0x000f0000 ) #define ERRFILE_acpipwr ( ERRFILE_ARCH | ERRFILE_CORE | 0x00100000 ) #define ERRFILE_cpuid ( ERRFILE_ARCH | ERRFILE_CORE | 0x00110000 ) +#define ERRFILE_rdtsc_timer ( ERRFILE_ARCH | ERRFILE_CORE | 0x00120000 ) #define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 ) #define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 ) diff --git a/src/arch/x86/include/bits/timer.h b/src/arch/x86/include/bits/timer.h deleted file mode 100644 index b0ff5ee11..000000000 --- a/src/arch/x86/include/bits/timer.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BITS_TIMER_H -#define _BITS_TIMER_H - -/** @file - * - * x86-specific timer API implementations - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/bios_timer.h> -#include <ipxe/rdtsc_timer.h> - -#endif /* _BITS_TIMER_H */ diff --git a/src/arch/x86/include/ipxe/bios_timer.h b/src/arch/x86/include/ipxe/bios_timer.h deleted file mode 100644 index 6b88a623c..000000000 --- a/src/arch/x86/include/ipxe/bios_timer.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _IPXE_BIOS_TIMER_H -#define _IPXE_BIOS_TIMER_H - -/** @file - * - * BIOS timer - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#ifdef TIMER_PCBIOS -#define TIMER_PREFIX_pcbios -#else -#define TIMER_PREFIX_pcbios __pcbios_ -#endif - -#include <ipxe/pit8254.h> - -/** - * Delay for a fixed number of microseconds - * - * @v usecs Number of microseconds for which to delay - */ -static inline __always_inline void -TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) { - /* BIOS timer is not high-resolution enough for udelay(), so - * we use the 8254 Programmable Interval Timer. - */ - pit8254_udelay ( usecs ); -} - -/** - * Get number of ticks per second - * - * @ret ticks_per_sec Number of ticks per second - */ -static inline __always_inline unsigned long -TIMER_INLINE ( pcbios, ticks_per_sec ) ( void ) { - /* BIOS timer ticks over at 18.2 ticks per second */ - return 18; -} - -#endif /* _IPXE_BIOS_TIMER_H */ diff --git a/src/arch/x86/include/ipxe/cpuid.h b/src/arch/x86/include/ipxe/cpuid.h index 2e2cc7c1a..a9df9f0de 100644 --- a/src/arch/x86/include/ipxe/cpuid.h +++ b/src/arch/x86/include/ipxe/cpuid.h @@ -57,6 +57,12 @@ struct x86_features { /** Get CPU model */ #define CPUID_MODEL 0x80000002UL +/** Get APM information */ +#define CPUID_APM 0x80000007UL + +/** Invariant TSC */ +#define CPUID_APM_EDX_TSC_INVARIANT 0x00000100UL + /** * Issue CPUID instruction * diff --git a/src/arch/x86/include/ipxe/rdtsc_timer.h b/src/arch/x86/include/ipxe/rdtsc_timer.h deleted file mode 100644 index 598f4bb08..000000000 --- a/src/arch/x86/include/ipxe/rdtsc_timer.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _IPXE_RDTSC_TIMER_H -#define _IPXE_RDTSC_TIMER_H - -/** @file - * - * RDTSC timer - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#ifdef TIMER_RDTSC -#define TIMER_PREFIX_rdtsc -#else -#define TIMER_PREFIX_rdtsc __rdtsc_ -#endif - -/** - * RDTSC values can easily overflow an unsigned long. We discard the - * low-order bits in order to obtain sensibly-scaled values. - */ -#define TSC_SHIFT 8 - -/** - * Get current system time in ticks - * - * @ret ticks Current time, in ticks - */ -static inline __always_inline unsigned long -TIMER_INLINE ( rdtsc, currticks ) ( void ) { - unsigned long ticks; - - __asm__ __volatile__ ( "rdtsc\n\t" - "shrdl %1, %%edx, %%eax\n\t" - : "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" ); - return ticks; -} - -#endif /* _IPXE_RDTSC_TIMER_H */ |