All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail.
@ 2018-01-16 18:16 Peter Jones
  2018-01-18 22:52 ` Daniel Kiper
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Jones @ 2018-01-16 18:16 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, David E . Box, Peter Jones

On my laptop running at 2.4GHz, if I run a VM where tsc calibration
using pmtimer will fail presuming a broken pmtimer, it takes ~51 seconds
to do so (as measured with the stopwatch on my phone), with a tsc delta
of 0x1cd1c85300, or around 125 billion cycles.

If instead of trying to wait for 5-200ms to show up on the pmtimer, we try
to wait for 5-200us, it decides it's broken in ~0x7998f9e TSCs, aka ~2
million cycles, or more or less instantly.

Additionally, this reading the pmtimer was returning 0xffffffff anyway,
and that's obviously an invalid return.  I've added a check for that and
0 so we don't bother waiting for the test if what we're seeing is dead
pins with no response at all.

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 grub-core/kern/i386/tsc_pmtimer.c | 43 ++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c
index c9c36169978..609402b8376 100644
--- a/grub-core/kern/i386/tsc_pmtimer.c
+++ b/grub-core/kern/i386/tsc_pmtimer.c
@@ -38,30 +38,53 @@ grub_pmtimer_wait_count_tsc (grub_port_t pmtimer,
   grub_uint64_t start_tsc;
   grub_uint64_t end_tsc;
   int num_iter = 0;
+  int bad_reads = 0;
 
-  start = grub_inl (pmtimer) & 0xffffff;
+  start = grub_inl (pmtimer) & 0x3fff;
   last = start;
   end = start + num_pm_ticks;
   start_tsc = grub_get_tsc ();
   while (1)
     {
-      cur = grub_inl (pmtimer) & 0xffffff;
+      cur = grub_inl (pmtimer);
+
+      /* If we get 10 reads in a row that are obviously dead pins, there's no
+	 reason to do this thousands of times.
+       */
+      if (cur == 0xffffffff || cur == 0)
+	{
+	  bad_reads++;
+	  grub_dprintf ("pmtimer", "cur: 0x%08x bad_reads: %d\n", cur, bad_reads);
+
+	  if (bad_reads == 10)
+	    return 0;
+	}
+      else if (bad_reads)
+	bad_reads = 0;
+
+      cur &= 0x3fff;
+
       if (cur < last)
-	cur |= 0x1000000;
+	cur |= 0x4000;
       num_iter++;
       if (cur >= end)
 	{
 	  end_tsc = grub_get_tsc ();
+	  grub_dprintf ("pmtimer", "tsc delta is 0x%016lx\n",
+			end_tsc - start_tsc);
 	  return end_tsc - start_tsc;
 	}
-      /* Check for broken PM timer.
-	 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
-	 if after this time we still don't have 1 ms on pmtimer, then
-	 pmtimer is broken.
+      /* Check for broken PM timer.  5000 TSCs is between 5us (10GHz) and
+	 200us (250 MHz).  If after this time we still don't have 1us on
+	 pmtimer, then pmtimer is broken.
        */
-      if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) {
-	return 0;
-      }
+      end_tsc = grub_get_tsc();
+      if ((num_iter & 0x3fff) == 0 && end_tsc - start_tsc > 5000)
+	{
+	  grub_dprintf ("pmtimer", "tsc delta is 0x%016lx\n",
+			end_tsc - start_tsc);
+	  return 0;
+	}
     }
 }
 
-- 
2.15.0



^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-02-20 19:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-16 18:16 [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail Peter Jones
2018-01-18 22:52 ` Daniel Kiper
2018-01-19 21:10   ` Peter Jones
2018-01-29 16:42     ` Daniel Kiper
2018-02-19 22:37       ` Peter Jones
2018-02-20 19:39         ` Daniel Kiper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.