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

Reply via email to