From d9a3bfead8236377c2f46eb75c4fd7fef93696ea Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Fri, 12 Feb 2016 11:40:51 +0100 Subject: [PATCH] Split pmtimer wait and tsc measurement from pmtimer tsc calibration. --- grub-core/Makefile.am | 2 ++ grub-core/kern/i386/tsc_pmtimer.c | 47 ++++++++++++++++++++----------- include/grub/i386/pmtimer.h | 37 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 include/grub/i386/pmtimer.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 90502cb1e..04e9395fd 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -107,6 +107,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h endif if COND_i386_coreboot @@ -162,6 +163,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h endif if COND_ia64_efi diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c index 2495e6fd4..c9c361699 100644 --- a/grub-core/kern/i386/tsc_pmtimer.c +++ b/grub-core/kern/i386/tsc_pmtimer.c @@ -24,44 +24,35 @@ #include #include #include +#include #include #include -int -grub_tsc_calibrate_from_pmtimer (void) +grub_uint64_t +grub_pmtimer_wait_count_tsc (grub_port_t pmtimer, + grub_uint16_t num_pm_ticks) { grub_uint32_t start; grub_uint32_t last; grub_uint32_t cur, end; - struct grub_acpi_fadt *fadt; - grub_port_t p; grub_uint64_t start_tsc; grub_uint64_t end_tsc; int num_iter = 0; - fadt = grub_acpi_find_fadt (); - if (!fadt) - return 0; - p = fadt->pmtimer; - if (!p) - return 0; - - start = grub_inl (p) & 0xffffff; + start = grub_inl (pmtimer) & 0xffffff; last = start; - /* It's 3.579545 MHz clock. Wait 1 ms. */ - end = start + 3580; + end = start + num_pm_ticks; start_tsc = grub_get_tsc (); while (1) { - cur = grub_inl (p) & 0xffffff; + cur = grub_inl (pmtimer) & 0xffffff; if (cur < last) cur |= 0x1000000; num_iter++; if (cur >= end) { end_tsc = grub_get_tsc (); - grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0); - return 1; + return end_tsc - start_tsc; } /* Check for broken PM timer. 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz) @@ -73,3 +64,25 @@ grub_tsc_calibrate_from_pmtimer (void) } } } + +int +grub_tsc_calibrate_from_pmtimer (void) +{ + struct grub_acpi_fadt *fadt; + grub_port_t pmtimer; + grub_uint64_t tsc_diff; + + fadt = grub_acpi_find_fadt (); + if (!fadt) + return 0; + pmtimer = fadt->pmtimer; + if (!pmtimer) + return 0; + + /* It's 3.579545 MHz clock. Wait 1 ms. */ + tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580); + if (tsc_diff == 0) + return 0; + grub_tsc_rate = grub_divmod64 ((1ULL << 32), tsc_diff, 0); + return 1; +} diff --git a/include/grub/i386/pmtimer.h b/include/grub/i386/pmtimer.h new file mode 100644 index 000000000..ac091806a --- /dev/null +++ b/include/grub/i386/pmtimer.h @@ -0,0 +1,37 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef KERNEL_CPU_PMTIMER_HEADER +#define KERNEL_CPU_PMTIMER_HEADER 1 + +#include +#include + +/* + Preconditions: + * Caller has ensured that both pmtimer and tsc are supported + * 1 <= num_pm_ticks <= 3580 + Return: + * Number of TSC ticks elapsed + * 0 on failure. +*/ +grub_uint64_t +EXPORT_FUNC(grub_pmtimer_wait_count_tsc) (grub_port_t pmtimer, + grub_uint16_t num_pm_ticks); + +#endif