From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1ebVn2-0005ba-6F for mharc-grub-devel@gnu.org; Tue, 16 Jan 2018 13:16:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55522) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ebVmy-0005WE-NX for grub-devel@gnu.org; Tue, 16 Jan 2018 13:16:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ebVmt-0002vc-Vs for grub-devel@gnu.org; Tue, 16 Jan 2018 13:16:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34224) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ebVmt-0002td-PJ for grub-devel@gnu.org; Tue, 16 Jan 2018 13:16:43 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AB3BB6AAE7; Tue, 16 Jan 2018 18:16:31 +0000 (UTC) Received: from trillian.uncooperative.org.com (dhcp-10-20-1-221.bss.redhat.com [10.20.1.221]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6ABCF5C3FA; Tue, 16 Jan 2018 18:16:25 +0000 (UTC) From: Peter Jones To: grub-devel@gnu.org Cc: Daniel Kiper , "David E . Box" , Peter Jones Subject: [PATCH] Make pmtimer tsc calibration not take 51 seconds to fail. Date: Tue, 16 Jan 2018 13:16:17 -0500 Message-Id: <20180116181617.2748-1-pjones@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 16 Jan 2018 18:16:36 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Jan 2018 18:16:50 -0000 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 --- 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