From a5576974cf8661b3f3a1f0074b16fa59033130c5 Mon Sep 17 00:00:00 2001 From: Sam Demeulemeester Date: Sun, 12 Jun 2022 22:32:30 +0200 Subject: [PATCH] Add ACPI Timer as the primary TSC correction source and PIT Timer as fallback --- app/main.c | 10 +++--- build32/Makefile | 1 + build64/Makefile | 1 + system/acpi.c | 2 +- system/acpi.h | 3 +- system/cpuinfo.c | 34 ------------------ system/timers.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ system/timers.h | 20 +++++++++++ 8 files changed, 124 insertions(+), 41 deletions(-) create mode 100644 system/timers.c create mode 100644 system/timers.h diff --git a/app/main.c b/app/main.c index d589761..16f7a3c 100644 --- a/app/main.c +++ b/app/main.c @@ -34,6 +34,7 @@ #include "smbios.h" #include "smp.h" #include "temperature.h" +#include "timers.h" #include "vmem.h" #include "unistd.h" @@ -221,6 +222,8 @@ static void global_init(void) acpi_init(); + timers_init(); + membw_init(); smbios_init(); @@ -281,10 +284,9 @@ static void global_init(void) for (int i = 0; i < pm_map_size; i++) { trace(0, "pm %0*x - %0*x", 2*sizeof(uintptr_t), pm_map[i].start, 2*sizeof(uintptr_t), pm_map[i].end); } - if (rsdp_addr != 0) { - trace(0, "ACPI RSDP found in %s at %0*x", rsdp_source, 2*sizeof(uintptr_t), rsdp_addr); - trace(0, "ACPI FADT found at %0*x", 2*sizeof(uintptr_t), fadt_addr); - trace(0, "ACPI HPET found at %0*x", 2*sizeof(uintptr_t), hpet_addr); + if (acpi_config.rsdp_addr != 0) { + trace(0, "ACPI RSDP (v%u.%u) found in %s at %0*x", acpi_config.ver_maj, acpi_config.ver_min, rsdp_source, 2*sizeof(uintptr_t), acpi_config.rsdp_addr); + trace(0, "ACPI FADT found at %0*x", 2*sizeof(uintptr_t), acpi_config.fadt_addr); } if (!load_addr_ok) { trace(0, "Cannot relocate program. Press any key to reboot..."); diff --git a/build32/Makefile b/build32/Makefile index 7fcc728..1e03597 100644 --- a/build32/Makefile +++ b/build32/Makefile @@ -33,6 +33,7 @@ SYS_OBJS = system/acpi.o \ system/smbus.o \ system/smp.o \ system/temperature.o \ + system/timers.o \ system/uhci.o \ system/usbhcd.o \ system/vmem.o \ diff --git a/build64/Makefile b/build64/Makefile index 4dcb791..99c5213 100644 --- a/build64/Makefile +++ b/build64/Makefile @@ -33,6 +33,7 @@ SYS_OBJS = system/acpi.o \ system/smbus.o \ system/smp.o \ system/temperature.o \ + system/timers.o \ system/uhci.o \ system/usbhcd.o \ system/vmem.o \ diff --git a/system/acpi.c b/system/acpi.c index 35c7f7c..b9d74f7 100644 --- a/system/acpi.c +++ b/system/acpi.c @@ -89,7 +89,7 @@ static const efi_guid_t EFI_ACPI_2_RDSP_GUID = { 0x8868e871, 0xe4f1, 0x11d3, {0x const char *rsdp_source = ""; -acpi_t acpi_config = {0, 0, 0, 0, 0, 0, 0, 0, false}; +acpi_t acpi_config = {0, 0, 0, 0, 0, 0, 0, false}; //------------------------------------------------------------------------------ // Private Functions diff --git a/system/acpi.h b/system/acpi.h index 72c818e..ee0a54d 100644 --- a/system/acpi.h +++ b/system/acpi.h @@ -22,10 +22,9 @@ * A struct containing various ACPI-related infos for later uses. */ -typedef struct { +typedef struct __attribute__ ((packed)) { uint8_t ver_maj; uint8_t ver_min; - uint64_t test; uintptr_t rsdp_addr; uintptr_t madt_addr; uintptr_t fadt_addr; diff --git a/system/cpuinfo.c b/system/cpuinfo.c index 0123d4e..f8522ef 100644 --- a/system/cpuinfo.c +++ b/system/cpuinfo.c @@ -33,7 +33,6 @@ // Constants //------------------------------------------------------------------------------ -#define PIT_TICKS_50mS 59659 // PIT clock is 1.193182MHz #define BENCH_MIN_START_ADR 0x1000000 // 16MB //------------------------------------------------------------------------------ @@ -861,37 +860,6 @@ static void determine_cpu_model(void) } } -static void measure_cpu_speed(void) -{ - if (cpuid_info.flags.rdtsc == 0) { - return; - } - - // Set up timer - outb((inb(0x61) & ~0x02) | 0x01, 0x61); - outb(0xb0, 0x43); - outb(PIT_TICKS_50mS & 0xff, 0x42); - outb(PIT_TICKS_50mS >> 8, 0x42); - - uint32_t start_time; - rdtscl(start_time); - - int loops = 0; - do { - loops++; - } while ((inb(0x61) & 0x20) == 0); - - uint32_t end_time; - rdtscl(end_time); - - uint32_t run_time = end_time - start_time; - - // Make sure we have a credible result - if (loops >= 4 && run_time >= 50000) { - clks_per_msec = run_time / 50; - } -} - static uint32_t memspeed(uintptr_t src, uint32_t len, int iter) { uintptr_t dst; @@ -1084,8 +1052,6 @@ void cpuinfo_init(void) determine_cache_size(); determine_cpu_model(); - - measure_cpu_speed(); } void membw_init(void) diff --git a/system/timers.c b/system/timers.c new file mode 100644 index 0000000..54794fa --- /dev/null +++ b/system/timers.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2020-2022 Martin Whitaker. +// Copyright (C) 2004-2022 Sam Demeulemeester. + +#include +#include +#include + +#include "acpi.h" +#include "cpuid.h" +#include "cpuinfo.h" +#include "io.h" +#include "tsc.h" + +//------------------------------------------------------------------------------ +// Constants +//------------------------------------------------------------------------------ + +#define PIT_TICKS_50mS 59659 // PIT clock is 1.193182MHz +#define APIC_TICKS_50mS 178977 // APIC clock is 3.579545MHz +#define BENCH_MIN_START_ADR 0x1000000 // 16MB + +//------------------------------------------------------------------------------ +// Private Functions +//------------------------------------------------------------------------------ + +static void correct_tsc(void) +{ + uint32_t start_time, end_time, run_time, counter; + int loops = 0; + + if (cpuid_info.flags.rdtsc == 0) { + return; + } + + // If available, use APIC Timer to find TSC correction factor + if (acpi_config.pm_is_io && acpi_config.pm_addr != 0) { + rdtscl(start_time); + + counter = inl(acpi_config.pm_addr); + + // Make sure counter is incrementing + if (inl(acpi_config.pm_addr) > counter) { + + while (1) { + if (inl(acpi_config.pm_addr) > (counter + APIC_TICKS_50mS) || loops > 1000000) { + break; + } + loops++; + } + + rdtscl(end_time); + + run_time = end_time - start_time; + + // Make sure we have a credible result + if (loops >= 10 && run_time >= 50000) { + clks_per_msec = run_time / 50; + return; + } + } + } + + // Use PIT Timer to find TSC correction factor if APIC not available + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + outb(0xb0, 0x43); + outb(PIT_TICKS_50mS & 0xff, 0x42); + outb(PIT_TICKS_50mS >> 8, 0x42); + + rdtscl(start_time); + + loops = 0; + do { + loops++; + } while ((inb(0x61) & 0x20) == 0); + + rdtscl(end_time); + + run_time = end_time - start_time; + + // Make sure we have a credible result + if (loops >= 4 && run_time >= 50000) { + clks_per_msec = run_time / 50; + } +} + +//------------------------------------------------------------------------------ +// Public Functions +//------------------------------------------------------------------------------ + +void timers_init(void) +{ + correct_tsc(); +} diff --git a/system/timers.h b/system/timers.h new file mode 100644 index 0000000..9c8d165 --- /dev/null +++ b/system/timers.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef _TIMERS_H_ +#define _TIMERS_H_ +/** + * \file + * + * Provides support for various timers sources + * + *//* + * Copyright (C) 2020-2022 Martin Whitaker. + * Copyright (C) 2004-2022 Sam Demeulemeester + */ + + +/** + * Initialize timers (to correct TSC frequency) + */ +void timers_init(void); + +#endif /* _TIMERS_H_ */