Add ACPI Timer as the primary TSC correction source and PIT Timer as fallback

This commit is contained in:
Sam Demeulemeester 2022-06-12 22:32:30 +02:00 committed by Sam Demeulemeester
parent eac4d03462
commit a5576974cf
8 changed files with 124 additions and 41 deletions

View File

@ -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...");

View File

@ -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 \

View File

@ -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 \

View File

@ -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

View File

@ -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;

View File

@ -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)

94
system/timers.c Normal file
View File

@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
// Copyright (C) 2004-2022 Sam Demeulemeester.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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();
}

20
system/timers.h Normal file
View File

@ -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_ */