hv: tsc: calibrate TSC by HPET

On some platforms CPUID.0x15:ECX is zero and CPUID.0x16 can
only return the TSC frequency in MHZ which is not accurate.
For example the TSC frequency obtained by CPUID.0x16 is 2300
MHZ and the TSC frequency calibrated by HPET is 2303.998 MHZ
which is much closer to the actual TSC frequency 2304.000 MHZ.
This patch adds the support of using HPET to calibrate TSC
when HPET is available and CPUID.0x15:ECX is zero.

v3->v4:
  - move calc_tsc_by_hpet into hpet_calibrate_tsc

v2->v3:
  - remove the NULL check in hpet_init
  - remove ""& 0xFFFFFFFFU" in tsc_read_hpet
  - add comment for the counter wrap in the low 32 bits in
    calc_tsc_by_hpet
  - use a dedicated function for hpet_calibrate_tsc

v1->v2:
  - change native_calibrate_tsc_cpuid_0x15/0x16 to
    native_calculate_tsc_cpuid_0x15/0x16
  - move hpet_init to BSP init
  - encapsulate both HPET and PIT calibration to one function
  - revise the commit message with an example"

Tracked-On: #7876
Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com>
Reviewed-by: Fei Li <fei1.li@intel.com>
This commit is contained in:
Jian Jun Chen
2022-07-05 15:36:41 +08:00
committed by acrnsi-robot
parent 047a11dff3
commit 97a2919138
5 changed files with 133 additions and 6 deletions

View File

@@ -59,6 +59,7 @@
#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module hardware interface table */
#define ACPI_SIG_RTCT "PTCT" /* Platform Tuning Configuration Table (Real-Time Configuration Table) */
#define ACPI_SIG_RTCT_V2 "RTCT" /* Platform Tuning Configuration Table (Real-Time Configuration Table) V2 */
#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
struct packed_gas {
uint8_t space_id;
@@ -242,12 +243,22 @@ struct acpi_table_tpm2 {
#endif
} __packed;
struct acpi_table_hpet {
struct acpi_table_header header;
uint32_t id;
struct packed_gas address;
uint8_t sequence;
uint16_t minimum_tick;
uint8_t flags;
} __packed;
void init_acpi(void);
void *get_acpi_tbl(const char *signature);
struct ioapic_info;
uint16_t parse_madt(uint32_t lapic_id_array[MAX_PCPU_NUM]);
uint8_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array);
void *parse_hpet(void);
#ifdef CONFIG_ACPI_PARSE_ENABLED
int32_t acpi_fixup(void);