]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Use ITC on IA64 rather than broken routine based on daytime.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 9 Jun 2012 08:52:39 +0000 (10:52 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Sat, 9 Jun 2012 08:52:39 +0000 (10:52 +0200)
* grub-core/kern/efi/efi.c (grub_rtc_get_time_ms) [__ia64__]: Remove on
ia64.
(grub_get_rtc) [__ia64__]: Likewise.
* grub-core/kern/ia64/efi/init.c (divisor): New variable.
(get_itc): New function.
(grub_rtc_get_time_ms): Likewise.
(grub_machine_init): Calibrate ITC.
* include/grub/efi/time.h (grub_get_rtc), (GRUB_TICKS_PER_SECOND):
Keep only on non-ia64. Don't export since it's broken and used only
if TSC is unavailable.

ChangeLog
grub-core/kern/efi/efi.c
grub-core/kern/ia64/efi/init.c
include/grub/efi/time.h

index 8fd09345744fb440ca7bc67c326f08b940be7855..4c4d5336c12f3a7919f34804641da7482ae11aa8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2012-06-09  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Use ITC on IA64 rather than broken routine based on daytime.
+
+       * grub-core/kern/efi/efi.c (grub_rtc_get_time_ms) [__ia64__]: Remove on
+       ia64.
+       (grub_get_rtc) [__ia64__]: Likewise.
+       * grub-core/kern/ia64/efi/init.c (divisor): New variable.
+       (get_itc): New function.
+       (grub_rtc_get_time_ms): Likewise.
+       (grub_machine_init): Calibrate ITC.
+       * include/grub/efi/time.h (grub_get_rtc), (GRUB_TICKS_PER_SECOND):
+       Keep only on non-ia64. Don't export since it's broken and used only
+       if TSC is unavailable.
+
 2012-06-09  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/disk/efi/efidisk.c (find_parent_device): Return the parent
index 6f12c76180a2ca9890a07e1c00c3bd238dd197ab..a59a6edbcda416a00ceb54b846b9e64f114f05c6 100644 (file)
@@ -230,6 +230,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
   return NULL;
 }
 
+#ifndef __ia64__
 grub_uint64_t
 grub_rtc_get_time_ms (void)
 {
@@ -250,6 +251,7 @@ grub_get_rtc (void)
 {
   return grub_rtc_get_time_ms ();
 }
+#endif
 
 #pragma GCC diagnostic ignored "-Wcast-align"
 
index e2fa580905a5afe43ece1a5dea4f482c0e587e09..7fa6fbf7125b41b9f941dc6673ce992c6df03bfe 100644 (file)
 #include <grub/kernel.h>
 #include <grub/efi/efi.h>
 
+static grub_uint64_t divisor = 1;
+
+static grub_uint64_t
+get_itc (void)
+{
+  grub_uint64_t ret;
+  asm volatile ("mov %0=ar.itc" : "=r" (ret));
+  return ret;
+}
+
+grub_uint64_t
+grub_rtc_get_time_ms (void)
+{
+  return get_itc () / divisor;
+}
+
 void
 grub_machine_init (void)
 {
+  grub_efi_event_t event;
+  grub_uint64_t before, after;
+  grub_efi_uintn_t idx;
   grub_efi_init ();
+
+  efi_call_5 (grub_efi_system_table->boot_services->create_event,
+             GRUB_EFI_EVT_TIMER, GRUB_EFI_TPL_CALLBACK, 0, 0, &event);
+
+  before = get_itc ();
+  efi_call_3 (grub_efi_system_table->boot_services->set_timer, event,
+             GRUB_EFI_TIMER_RELATIVE, 200000);
+  efi_call_3 (grub_efi_system_table->boot_services->wait_for_event, 1,
+             &event, &idx);
+  after = get_itc ();
+  efi_call_1 (grub_efi_system_table->boot_services->close_event, event);
+  divisor = (after - before + 5) / 20;
+  if (divisor == 0)
+    divisor = 800000;
   grub_install_get_time_ms (grub_rtc_get_time_ms);
 }
 
index 51b3373096322abfc5e6f0e35f0e76cda28739d6..1c38ac0e724fa471e028eef722622a5609cd2ce3 100644 (file)
 
 #include <grub/symbol.h>
 
+#ifndef __ia64__
 #define GRUB_TICKS_PER_SECOND  1000
 
 /* Return the real time in ticks.  */
-grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+grub_uint32_t grub_get_rtc (void);
+#endif
 
 #endif /* ! GRUB_EFI_TIME_HEADER */