grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Use UEFI Time Service to calibrate TSC


From: Michael Chang
Subject: [PATCH] Use UEFI Time Service to calibrate TSC
Date: Mon, 9 Nov 2015 15:07:46 +0800
User-agent: Mutt/1.5.21 (2010-09-15)

This patch tries to detect PIT timer is broken and use UEFI Time Service
to calibrate TSC.
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]