Messages in this thread Patch in this message | | | From | Michael Kelley <> | Subject | [PATCH v2 char-misc 1/1] x86/hyperv: Fix PIT shutdown quirk | Date | Mon, 22 Oct 2018 16:34:13 +0000 |
| |
pit_shutdown() doesn't work on Hyper-V because of a quirk in the PIT emulation. After shutdown the emulated PIT continues to interrupt @18.2 HZ. This problem exists in all versions of Hyper-V and just had not previously been noticed. So replace the normal PIT shutdown function with an alternate version that works on Hyper-V.
The alternate shutdown function could go in the i8253.c module, but it seems better to keep the hack with the Hyper-V code rather than clutter up i8253.c with #ifdef CONFIG_HYPERV.
Signed-off-by: Michael Kelley <mikelley@microsoft.com> --- Changes in v2: * Fixed commit message and comment in the code to indicate that the PIT continues to interrupt @18.2 HZ, not every 18.2 seconds. [Dexuan Cui]
--- arch/x86/hyperv/hv_init.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 7abb09e..514fcbe 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -32,6 +32,9 @@ #include <linux/slab.h> #include <linux/cpuhotplug.h> +#include <linux/io.h> +#include <linux/i8253.h> + #ifdef CONFIG_HYPERV_TSCPAGE static struct ms_hyperv_tsc_page *tsc_pg; @@ -97,6 +100,26 @@ static u64 read_hv_clock_msr(struct clocksource *arg) u32 hv_max_vp_index; +#if defined(CONFIG_CLKEVT_I8253) +/* + * Hyper-V emulation of the PIT has a quirk such that the + * normal i8253 pit_shutdown() routine doesn't stop the PIT. + * It keeps interrupting @18.2 HZ. This alternate + * shutdown routine mirrors the normal one, but does not + * set the counter value to zero. + */ +static int hyperv_pit_shutdown(struct clock_event_device *evt) +{ + if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt)) + return 0; + + raw_spin_lock(&i8253_lock); + outb_p(0x30, PIT_MODE); + raw_spin_unlock(&i8253_lock); + return 0; +} +#endif + static int hv_cpu_init(unsigned int cpu) { u64 msr_vp_index; @@ -325,6 +348,14 @@ void __init hyperv_init(void) if (cpuhp < 0) goto free_vp_assist_page; +#if defined(CONFIG_CLKEVT_I8253) + /* + * Override the PIT shutdown routine due to a quirk in + * Hyper-V emulation of the PIT. + */ + i8253_clockevent.set_state_shutdown = hyperv_pit_shutdown; +#endif + /* * Setup the hypercall page and enable hypercalls. * 1. Register the guest ID -- 1.8.3.1
| |