Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86-timers-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 timer updates from Thomas Gleixner:

- Use the topology information of number of packages for making the
decision about TSC trust instead of using the number of online nodes
which is not reflecting the real topology.

- Stop the PIT timer 0 when its not in use as to stop pointless
emulation in the VMM.

- Fix the PIT timer stop sequence for timer 0 so it truly stops both
real hardware and buggy VMM emulations.

* tag 'x86-timers-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/tsc: Check for sockets instead of CPUs to make code match comment
clockevents/drivers/i8253: Fix stop sequence for timer 0
x86/i8253: Disable PIT timer 0 when not in use
x86/tsc: Use topology_max_packages() to get package number

+50 -37
-11
arch/x86/kernel/cpu/mshyperv.c
··· 16 16 #include <linux/interrupt.h> 17 17 #include <linux/irq.h> 18 18 #include <linux/kexec.h> 19 - #include <linux/i8253.h> 20 19 #include <linux/random.h> 21 20 #include <asm/processor.h> 22 21 #include <asm/hypervisor.h> ··· 535 536 */ 536 537 if (efi_enabled(EFI_BOOT)) 537 538 x86_platform.get_nmi_reason = hv_get_nmi_reason; 538 - 539 - /* 540 - * Hyper-V VMs have a PIT emulation quirk such that zeroing the 541 - * counter register during PIT shutdown restarts the PIT. So it 542 - * continues to interrupt @18.2 HZ. Setting i8253_clear_counter 543 - * to false tells pit_shutdown() not to zero the counter so that 544 - * the PIT really is shutdown. Generation 2 VMs don't have a PIT, 545 - * and setting this value has no effect. 546 - */ 547 - i8253_clear_counter_on_shutdown = false; 548 539 549 540 #if IS_ENABLED(CONFIG_HYPERV) 550 541 if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) ||
+9 -2
arch/x86/kernel/i8253.c
··· 8 8 #include <linux/timex.h> 9 9 #include <linux/i8253.h> 10 10 11 + #include <asm/hypervisor.h> 11 12 #include <asm/apic.h> 12 13 #include <asm/hpet.h> 13 14 #include <asm/time.h> ··· 40 39 41 40 bool __init pit_timer_init(void) 42 41 { 43 - if (!use_pit()) 42 + if (!use_pit()) { 43 + /* 44 + * Don't just ignore the PIT. Ensure it's stopped, because 45 + * VMMs otherwise steal CPU time just to pointlessly waggle 46 + * the (masked) IRQ. 47 + */ 48 + clockevent_i8253_disable(); 44 49 return false; 45 - 50 + } 46 51 clockevent_i8253_init(true); 47 52 global_clock_event = &i8253_clockevent; 48 53 return true;
+4 -6
arch/x86/kernel/tsc.c
··· 28 28 #include <asm/apic.h> 29 29 #include <asm/cpu_device_id.h> 30 30 #include <asm/i8259.h> 31 + #include <asm/topology.h> 31 32 #include <asm/uv/uv.h> 32 33 33 34 unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ ··· 1254 1253 * - TSC which does not stop in C-States 1255 1254 * - the TSC_ADJUST register which allows to detect even minimal 1256 1255 * modifications 1257 - * - not more than two sockets. As the number of sockets cannot be 1258 - * evaluated at the early boot stage where this has to be 1259 - * invoked, check the number of online memory nodes as a 1260 - * fallback solution which is an reasonable estimate. 1256 + * - not more than four packages 1261 1257 */ 1262 1258 if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && 1263 1259 boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && 1264 1260 boot_cpu_has(X86_FEATURE_TSC_ADJUST) && 1265 - nr_online_nodes <= 4) 1261 + topology_max_packages() <= 4) 1266 1262 tsc_disable_clocksource_watchdog(); 1267 1263 } 1268 1264 ··· 1288 1290 */ 1289 1291 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { 1290 1292 /* assume multi socket systems are not synchronized: */ 1291 - if (num_possible_cpus() > 1) 1293 + if (topology_max_packages() > 1) 1292 1294 return 1; 1293 1295 } 1294 1296
+36 -17
drivers/clocksource/i8253.c
··· 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 ··· 101 108 #endif 102 109 103 110 #ifdef CONFIG_CLKEVT_I8253 111 + void clockevent_i8253_disable(void) 112 + { 113 + raw_spin_lock(&i8253_lock); 114 + 115 + /* 116 + * Writing the MODE register should stop the counter, according to 117 + * the datasheet. This appears to work on real hardware (well, on 118 + * modern Intel and AMD boxes; I didn't dig the Pegasos out of the 119 + * shed). 120 + * 121 + * However, some virtual implementations differ, and the MODE change 122 + * doesn't have any effect until either the counter is written (KVM 123 + * in-kernel PIT) or the next interrupt (QEMU). And in those cases, 124 + * it may not stop the *count*, only the interrupts. Although in 125 + * the virt case, that probably doesn't matter, as the value of the 126 + * counter will only be calculated on demand if the guest reads it; 127 + * it's the interrupts which cause steal time. 128 + * 129 + * Hyper-V apparently has a bug where even in mode 0, the IRQ keeps 130 + * firing repeatedly if the counter is running. But it *does* do the 131 + * right thing when the MODE register is written. 132 + * 133 + * So: write the MODE and then load the counter, which ensures that 134 + * the IRQ is stopped on those buggy virt implementations. And then 135 + * write the MODE again, which is the right way to stop it. 136 + */ 137 + outb_p(0x30, PIT_MODE); 138 + outb_p(0, PIT_CH0); 139 + outb_p(0, PIT_CH0); 140 + 141 + outb_p(0x30, PIT_MODE); 142 + 143 + raw_spin_unlock(&i8253_lock); 144 + } 145 + 104 146 static int pit_shutdown(struct clock_event_device *evt) 105 147 { 106 148 if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt)) 107 149 return 0; 108 150 109 - raw_spin_lock(&i8253_lock); 110 - 111 - outb_p(0x30, PIT_MODE); 112 - 113 - if (i8253_clear_counter_on_shutdown) { 114 - outb_p(0, PIT_CH0); 115 - outb_p(0, PIT_CH0); 116 - } 117 - 118 - raw_spin_unlock(&i8253_lock); 151 + clockevent_i8253_disable(); 119 152 return 0; 120 153 } 121 154
+1 -1
include/linux/i8253.h
··· 21 21 #define PIT_LATCH ((PIT_TICK_RATE + HZ/2) / HZ) 22 22 23 23 extern raw_spinlock_t i8253_lock; 24 - extern bool i8253_clear_counter_on_shutdown; 25 24 extern struct clock_event_device i8253_clockevent; 26 25 extern void clockevent_i8253_init(bool oneshot); 26 + extern void clockevent_i8253_disable(void); 27 27 28 28 extern void setup_pit_timer(void); 29 29