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:
parent
3d2c8048da
commit
d43a5ee651
13 changed files with 451 additions and 121 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue