Allow users to remove the CPU timestamp counter support at compile time. The PMTIMER is frequently used instead of the TSC and this compile time option allows one to strip a few bytes from the final binary. This change also defaults the internal timer to use the PIT based timer until the PMTIMER or TSC is detected.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/Kconfig | 10 ++++++++-- src/hw/timer.c | 23 ++++++++--------------- 2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 14c38fb..b14e554 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -316,10 +316,16 @@ menu "Hardware support" help Initialize the Memory Type Range Registers (on emulators). config PMTIMER - bool "Use ACPI timer" + bool "Support ACPI timer" default y help - Use the ACPI timer instead of the TSC for timekeeping (on qemu). + Detect and use the ACPI timer for timekeeping. + config TSC_TIMER + bool "Support CPU timestamp counter as timer" + default y + help + Support for using the CPU timestamp counter as an internal + timing source. endmenu
menu "BIOS interfaces" diff --git a/src/hw/timer.c b/src/hw/timer.c index 5edc9fd..882b772 100644 --- a/src/hw/timer.c +++ b/src/hw/timer.c @@ -49,8 +49,8 @@ #define PMTIMER_HZ 3579545 // Underlying Hz of the PM Timer #define PMTIMER_TO_PIT 3 // Ratio of pmtimer rate to pit rate
-u32 TimerKHz VARFSEG; -u16 TimerPort VARFSEG; +u32 TimerKHz VARFSEG = DIV_ROUND_UP(PMTIMER_HZ, 1000 * PMTIMER_TO_PIT); +u16 TimerPort VARFSEG = PORT_PIT_COUNTER0; u8 ShiftTSC VARFSEG;
@@ -92,6 +92,7 @@ tsctimer_setup(void) t = (t + 1) >> 1; } TimerKHz = DIV_ROUND_UP((u32)t, 1000 * PMTIMER_TO_PIT); + TimerPort = 0;
dprintf(1, "CPU Mhz=%u\n", (TimerKHz << ShiftTSC) / 1000); } @@ -100,24 +101,16 @@ tsctimer_setup(void) void timer_setup(void) { - if (CONFIG_PMTIMER && TimerPort) { - dprintf(3, "pmtimer already configured; will not calibrate TSC\n"); + if (!CONFIG_TSC_TIMER || (CONFIG_PMTIMER && TimerPort != PORT_PIT_COUNTER0)) return; - }
+ // Check if CPU has a timestamp counter u32 eax, ebx, ecx, edx, cpuid_features = 0; cpuid(0, &eax, &ebx, &ecx, &edx); if (eax > 0) cpuid(1, &eax, &ebx, &ecx, &cpuid_features); - - if (!(cpuid_features & CPUID_TSC)) { - TimerPort = PORT_PIT_COUNTER0; - TimerKHz = DIV_ROUND_UP(PMTIMER_HZ, 1000 * PMTIMER_TO_PIT); - dprintf(3, "386/486 class CPU. Using TSC emulation\n"); - return; - } - - tsctimer_setup(); + if (cpuid_features & CPUID_TSC) + tsctimer_setup(); }
void @@ -154,7 +147,7 @@ static u32 timer_read(void) { u16 port = GET_GLOBAL(TimerPort); - if (!port) + if (CONFIG_TSC_TIMER && !port) // Read from CPU TSC return rdtscll() >> GET_GLOBAL(ShiftTSC); if (CONFIG_PMTIMER && port != PORT_PIT_COUNTER0)