[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<SN6PR02MB41571AE611E7D249DABFE56DD4B22@SN6PR02MB4157.namprd02.prod.outlook.com>
Date: Thu, 1 Aug 2024 16:14:14 +0000
From: Michael Kelley <mhklinux@...look.com>
To: Thomas Gleixner <tglx@...utronix.de>, "lirongqing@...du.com"
<lirongqing@...du.com>, "seanjc@...gle.com" <seanjc@...gle.com>,
"kys@...rosoft.com" <kys@...rosoft.com>, "haiyangz@...rosoft.com"
<haiyangz@...rosoft.com>, "wei.liu@...nel.org" <wei.liu@...nel.org>,
"decui@...rosoft.com" <decui@...rosoft.com>, "mingo@...hat.com"
<mingo@...hat.com>, "bp@...en8.de" <bp@...en8.de>,
"dave.hansen@...ux.intel.com" <dave.hansen@...ux.intel.com>, "x86@...nel.org"
<x86@...nel.org>, "linux-hyperv@...r.kernel.org"
<linux-hyperv@...r.kernel.org>, "linux-kernel@...r.kernel.org"
<linux-kernel@...r.kernel.org>
Subject: RE: [PATCH] clockevents/drivers/i8253: Do not zero timer counter in
shutdown
From: Thomas Gleixner <tglx@...utronix.de> Sent: Thursday, August 1, 2024 7:21 AM
>
> On Tue, Feb 07 2023 at 09:14, lirongqing@...du.com wrote:
> > @@ -117,11 +110,6 @@ static int pit_shutdown(struct clock_event_device *evt)
> >
> > outb_p(0x30, PIT_MODE);
> >
> > - if (i8253_clear_counter_on_shutdown) {
> > - outb_p(0, PIT_CH0);
> > - outb_p(0, PIT_CH0);
> > - }
> > -
>
> The stop sequence is wrong:
>
> When there is a count in progress, writing a new LSB before the
> counter has counted down to 0 and rolled over to FFFFh, WILL stop
> the counter. However, if the LSB is loaded AFTER the counter has
> rolled over to FFFFh, so that an MSB now exists in the counter, then
> the counter WILL NOT stop.
>
> The original i8253 datasheet says:
>
> 1) Write 1st byte stops the current counting
> 2) Write 2nd byte starts the new count
>
> The above does not make sure it actually has not rolled over and it
> obviously is initiating the new count by writing the MSB too. So it does
> not work on real hardware either.
>
> The proper sequence is:
>
> // Switch to mode 0
> outb_p(0x30, PIT_MODE);
> // Load the maximum value to ensure there is no rollover
> outb_p(0xff, PIT_CH0);
> // Writing MSB starts the counter from 0xFFFF and clears rollover
> outb_p(0xff, PIT_CH0);
> // Stop the counter by writing only LSB
> outb_p(0xff, PIT_CH0);
>
> That works on real hardware and fails on KVM... So much for the claim
> that KVM follows the spec :)
>
> So yes, the code is buggy, but instead of deleting it, we rather fix it,
> no?
>
FWIW, in Hyper-V guests with the Hyper-V quirk removed, tglx's new
sequence does *not* stop the PIT. But this sequence does:
outb_p(0x30, PIT_MODE);
outb_p(0xff, PIT_CH0);
outb_p(0xff, PIT_CH0);
outb_p(0x30, PIT_MODE);
outb_p(0xff, PIT_CH0);
I don't have a convenient way to test my sequence on KVM.
Michael
Powered by blists - more mailing lists