Commit f0a282f0 authored by David Woodhouse's avatar David Woodhouse Committed by Wentao Guan
Browse files

x86/i8253: Disable PIT timer 0 when not in use

stable inclusion
from stable-v6.6.79
commit c02c52036e6d68341f7e834d83166f3d50b27503
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBXANC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c02c52036e6d68341f7e834d83166f3d50b27503



--------------------------------

commit 70e6b7d9ae3c63df90a7bba7700e8d5c300c3c60 upstream.

Leaving the PIT interrupt running can cause noticeable steal time for
virtual guests. The VMM generally has a timer which toggles the IRQ input
to the PIC and I/O APIC, which takes CPU time away from the guest. Even
on real hardware, running the counter may use power needlessly (albeit
not much).

Make sure it's turned off if it isn't going to be used.

Signed-off-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarMichael Kelley <mhkelley@outlook.com>
Link: https://lore.kernel.org/all/20240802135555.564941-1-dwmw2@infradead.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit c02c52036e6d68341f7e834d83166f3d50b27503)
Signed-off-by: default avatarWentao Guan <guanwentao@uniontech.com>
parent 6a1d6cda
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/timex.h>
#include <linux/i8253.h>

#include <asm/hypervisor.h>
#include <asm/apic.h>
#include <asm/hpet.h>
#include <asm/time.h>
@@ -39,9 +40,15 @@ static bool __init use_pit(void)

bool __init pit_timer_init(void)
{
	if (!use_pit())
	if (!use_pit()) {
		/*
		 * Don't just ignore the PIT. Ensure it's stopped, because
		 * VMMs otherwise steal CPU time just to pointlessly waggle
		 * the (masked) IRQ.
		 */
		clockevent_i8253_disable();
		return false;

	}
	clockevent_i8253_init(true);
	global_clock_event = &i8253_clockevent;
	return true;
+9 −4
Original line number Diff line number Diff line
@@ -108,11 +108,8 @@ int __init clocksource_i8253_init(void)
#endif

#ifdef CONFIG_CLKEVT_I8253
static int pit_shutdown(struct clock_event_device *evt)
void clockevent_i8253_disable(void)
{
	if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
		return 0;

	raw_spin_lock(&i8253_lock);

	outb_p(0x30, PIT_MODE);
@@ -123,6 +120,14 @@ static int pit_shutdown(struct clock_event_device *evt)
	}

	raw_spin_unlock(&i8253_lock);
}

static int pit_shutdown(struct clock_event_device *evt)
{
	if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
		return 0;

	clockevent_i8253_disable();
	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ extern raw_spinlock_t i8253_lock;
extern bool i8253_clear_counter_on_shutdown;
extern struct clock_event_device i8253_clockevent;
extern void clockevent_i8253_init(bool oneshot);
extern void clockevent_i8253_disable(void);

extern void setup_pit_timer(void);