|
20 | 20 | DEFINE_RAW_SPINLOCK(i8253_lock);
|
21 | 21 | EXPORT_SYMBOL(i8253_lock);
|
22 | 22 |
|
23 |
| -/* |
24 |
| - * Handle PIT quirk in pit_shutdown() where zeroing the counter register |
25 |
| - * restarts the PIT, negating the shutdown. On platforms with the quirk, |
26 |
| - * platform specific code can set this to false. |
27 |
| - */ |
28 |
| -bool i8253_clear_counter_on_shutdown __ro_after_init = true; |
29 |
| - |
30 | 23 | #ifdef CONFIG_CLKSRC_I8253
|
31 | 24 | /*
|
32 | 25 | * Since the PIT overflows every tick, its not very useful
|
@@ -112,12 +105,33 @@ void clockevent_i8253_disable(void)
|
112 | 105 | {
|
113 | 106 | raw_spin_lock(&i8253_lock);
|
114 | 107 |
|
| 108 | + /* |
| 109 | + * Writing the MODE register should stop the counter, according to |
| 110 | + * the datasheet. This appears to work on real hardware (well, on |
| 111 | + * modern Intel and AMD boxes; I didn't dig the Pegasos out of the |
| 112 | + * shed). |
| 113 | + * |
| 114 | + * However, some virtual implementations differ, and the MODE change |
| 115 | + * doesn't have any effect until either the counter is written (KVM |
| 116 | + * in-kernel PIT) or the next interrupt (QEMU). And in those cases, |
| 117 | + * it may not stop the *count*, only the interrupts. Although in |
| 118 | + * the virt case, that probably doesn't matter, as the value of the |
| 119 | + * counter will only be calculated on demand if the guest reads it; |
| 120 | + * it's the interrupts which cause steal time. |
| 121 | + * |
| 122 | + * Hyper-V apparently has a bug where even in mode 0, the IRQ keeps |
| 123 | + * firing repeatedly if the counter is running. But it *does* do the |
| 124 | + * right thing when the MODE register is written. |
| 125 | + * |
| 126 | + * So: write the MODE and then load the counter, which ensures that |
| 127 | + * the IRQ is stopped on those buggy virt implementations. And then |
| 128 | + * write the MODE again, which is the right way to stop it. |
| 129 | + */ |
115 | 130 | outb_p(0x30, PIT_MODE);
|
| 131 | + outb_p(0, PIT_CH0); |
| 132 | + outb_p(0, PIT_CH0); |
116 | 133 |
|
117 |
| - if (i8253_clear_counter_on_shutdown) { |
118 |
| - outb_p(0, PIT_CH0); |
119 |
| - outb_p(0, PIT_CH0); |
120 |
| - } |
| 134 | + outb_p(0x30, PIT_MODE); |
121 | 135 |
|
122 | 136 | raw_spin_unlock(&i8253_lock);
|
123 | 137 | }
|
|
0 commit comments