tsc: Use alternative delay sources whenever appropriate.

PIT isn't available on some of new hardware including Hyper-V. So
use pmtimer for calibration. Moreover pmtimer calibration is faster, so
use it on coreboor where booting time is important.

Based on patch by Michael Chang.
This commit is contained in:
Vladimir Serbinenko 2015-11-13 16:14:53 +01:00
parent 3d2c8048da
commit d43a5ee651
13 changed files with 451 additions and 121 deletions

View file

@ -67,10 +67,14 @@ struct grub_acpi_fadt
grub_uint32_t dsdt_addr;
grub_uint8_t somefields1[20];
grub_uint32_t pm1a;
grub_uint8_t somefields2[64];
grub_uint8_t somefields2[8];
grub_uint32_t pmtimer;
grub_uint8_t somefields3[32];
grub_uint32_t flags;
grub_uint8_t somefields4[16];
grub_uint64_t facs_xaddr;
grub_uint64_t dsdt_xaddr;
grub_uint8_t somefields3[96];
grub_uint8_t somefields5[96];
} GRUB_PACKED;
#define GRUB_ACPI_MADT_SIGNATURE "APIC"
@ -176,9 +180,9 @@ enum
#ifndef GRUB_DSDT_TEST
struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void);
struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void);
struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void);
struct grub_acpi_rsdp_v20 *grub_machine_acpi_get_rsdpv2 (void);
grub_uint8_t grub_byte_checksum (void *base, grub_size_t size);
struct grub_acpi_rsdp_v10 *EXPORT_FUNC(grub_machine_acpi_get_rsdpv1) (void);
struct grub_acpi_rsdp_v20 *EXPORT_FUNC(grub_machine_acpi_get_rsdpv2) (void);
grub_uint8_t EXPORT_FUNC(grub_byte_checksum) (void *base, grub_size_t size);
grub_err_t grub_acpi_create_ebda (void);
@ -234,4 +238,7 @@ enum
GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP = 0x87,
};
struct grub_acpi_fadt *
grub_acpi_find_fadt (void);
#endif /* ! GRUB_ACPI_HEADER */

View file

@ -20,9 +20,35 @@
#define KERNEL_CPU_TSC_HEADER 1
#include <grub/types.h>
#include <grub/i386/cpuid.h>
void grub_tsc_init (void);
/* In ms per 2^32 ticks. */
extern grub_uint32_t EXPORT_VAR(grub_tsc_rate);
int
grub_tsc_calibrate_from_xen (void);
int
grub_tsc_calibrate_from_efi (void);
int
grub_tsc_calibrate_from_pmtimer (void);
int
grub_tsc_calibrate_from_pit (void);
/* Read the TSC value, which increments with each CPU clock cycle. */
static __inline grub_uint64_t
grub_get_tsc (void)
{
grub_uint32_t lo, hi;
grub_uint32_t a,b,c,d;
/* The CPUID instruction is a 'serializing' instruction, and
avoids out-of-order execution of the RDTSC instruction. */
grub_cpuid (0,a,b,c,d);
/* Read TSC value. We cannot use "=A", since this would use
%rax on x86_64. */
__asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
return (((grub_uint64_t) hi) << 32) | lo;
}
#endif /* ! KERNEL_CPU_TSC_HEADER */