Skip to content

Commit 25ffe92

Browse files
dwmw2gregkh
authored andcommitted
x86/i8253: Disable PIT timer 0 when not in use
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: David Woodhouse <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 552e793 commit 25ffe92

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

arch/x86/kernel/i8253.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/timex.h>
99
#include <linux/i8253.h>
1010

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

4041
bool __init pit_timer_init(void)
4142
{
42-
if (!use_pit())
43+
if (!use_pit()) {
44+
/*
45+
* Don't just ignore the PIT. Ensure it's stopped, because
46+
* VMMs otherwise steal CPU time just to pointlessly waggle
47+
* the (masked) IRQ.
48+
*/
49+
clockevent_i8253_disable();
4350
return false;
44-
51+
}
4552
clockevent_i8253_init(true);
4653
global_clock_event = &i8253_clockevent;
4754
return true;

drivers/clocksource/i8253.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,8 @@ int __init clocksource_i8253_init(void)
108108
#endif
109109

110110
#ifdef CONFIG_CLKEVT_I8253
111-
static int pit_shutdown(struct clock_event_device *evt)
111+
void clockevent_i8253_disable(void)
112112
{
113-
if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
114-
return 0;
115-
116113
raw_spin_lock(&i8253_lock);
117114

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

125122
raw_spin_unlock(&i8253_lock);
123+
}
124+
125+
static int pit_shutdown(struct clock_event_device *evt)
126+
{
127+
if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
128+
return 0;
129+
130+
clockevent_i8253_disable();
126131
return 0;
127132
}
128133

include/linux/i8253.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ extern raw_spinlock_t i8253_lock;
2424
extern bool i8253_clear_counter_on_shutdown;
2525
extern struct clock_event_device i8253_clockevent;
2626
extern void clockevent_i8253_init(bool oneshot);
27+
extern void clockevent_i8253_disable(void);
2728

2829
extern void setup_pit_timer(void);
2930

0 commit comments

Comments
 (0)