On Mon, Nov 9, 2015 at 10:07 AM, Michael Chang <mch...@suse.com> wrote: > This patch tries to detect PIT timer is broken and use UEFI Time Service > to calibrate TSC.
Second try :) https://lists.gnu.org/archive/html/grub-devel/2014-11/msg00079.html Although I think that this one is acceptable - it is used as fallback only. Will it also catch the case when PIT is not present at all? > --- > grub-core/kern/i386/tsc.c | 33 +++++++++++++++++++++++++++++---- > 1 files changed, 29 insertions(+), 4 deletions(-) > > diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c > index bc441d0..bd24cea 100644 > --- a/grub-core/kern/i386/tsc.c > +++ b/grub-core/kern/i386/tsc.c > @@ -29,6 +29,10 @@ > #include <grub/xen.h> > #else > #include <grub/i386/pit.h> > +#ifdef GRUB_MACHINE_EFI > +#include <grub/efi/efi.h> > +#include <grub/efi/api.h> > +#endif > #endif > #include <grub/cpu/io.h> > > @@ -72,7 +76,7 @@ grub_cpu_is_tsc_supported (void) > } > > static void > -grub_pit_wait (grub_uint16_t tics) > +grub_pit_wait (grub_uint16_t tics, int *is_started) > { > /* Disable timer2 gate and speaker. */ > grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) > @@ -90,8 +94,17 @@ grub_pit_wait (grub_uint16_t tics) > | GRUB_PIT_SPK_TMR2, > GRUB_PIT_SPEAKER_PORT); > > - /* Wait. */ > - while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == > 0x00); > + if ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH)) > + { > + /* The ticks have expired too fast to know the counting really started > or not */ > + *is_started = 0; > + } > + else > + { > + *is_started = 1; > + /* Wait. */ > + while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == > 0x00); > + } > > /* Disable timer2 gate and speaker. */ > grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) > @@ -117,11 +130,23 @@ calibrate_tsc (void) > { > /* First calibrate the TSC rate (relative, not absolute time). */ > grub_uint64_t end_tsc; > + int is_started; > > tsc_boot_time = grub_get_tsc (); > - grub_pit_wait (0xffff); > + grub_pit_wait (0xffff, &is_started); > end_tsc = grub_get_tsc (); > > +#ifdef GRUB_MACHINE_EFI > + /* The PIT is broken as 55ms is too sufficent to any cpu to catch it */ > + if (!is_started) > + { > + /* Use EFI Time Service to calibrate TSC */ > + tsc_boot_time = grub_get_tsc (); > + efi_call_1 (grub_efi_system_table->boot_services->stall, 54925); > + end_tsc = grub_get_tsc (); > + } > +#endif > + > grub_tsc_rate = 0; > if (end_tsc > tsc_boot_time) > grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, > 0); > -- > 1.7.3.4 > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel