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.

x86/entry: Remove unwanted instrumentation in common_interrupt()

common_interrupt() and related variants call kvm_set_cpu_l1tf_flush_l1d(),
which is neither marked noinstr nor __always_inline.

So compiler puts it out of line and adds instrumentation to it. Since the
call is inside of instrumentation_begin/end(), objtool does not warn about
it.

The manifestation is that KCOV produces spurious coverage in
kvm_set_cpu_l1tf_flush_l1d() in random places because the call happens when
preempt count is not yet updated to say that the kernel is in an interrupt.

Mark kvm_set_cpu_l1tf_flush_l1d() as __always_inline and move it out of the
instrumentation_begin/end() section. It only calls __this_cpu_write()
which is already safe to call in noinstr contexts.

Fixes: 6368558c3710 ("x86/entry: Provide IDTENTRY_SYSVEC")
Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Alexander Potapenko <glider@google.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/all/3f9a1de9e415fcb53d07dc9e19fa8481bb021b1b.1718092070.git.dvyukov@google.com

authored by

Dmitry Vyukov and committed by
Thomas Gleixner
477d81a1 de9c2c66

+9 -5
+6 -2
arch/x86/include/asm/hardirq.h
··· 69 69 #define local_softirq_pending_ref pcpu_hot.softirq_pending 70 70 71 71 #if IS_ENABLED(CONFIG_KVM_INTEL) 72 - static inline void kvm_set_cpu_l1tf_flush_l1d(void) 72 + /* 73 + * This function is called from noinstr interrupt contexts 74 + * and must be inlined to not get instrumentation. 75 + */ 76 + static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) 73 77 { 74 78 __this_cpu_write(irq_stat.kvm_cpu_l1tf_flush_l1d, 1); 75 79 } ··· 88 84 return __this_cpu_read(irq_stat.kvm_cpu_l1tf_flush_l1d); 89 85 } 90 86 #else /* !IS_ENABLED(CONFIG_KVM_INTEL) */ 91 - static inline void kvm_set_cpu_l1tf_flush_l1d(void) { } 87 + static __always_inline void kvm_set_cpu_l1tf_flush_l1d(void) { } 92 88 #endif /* IS_ENABLED(CONFIG_KVM_INTEL) */ 93 89 94 90 #endif /* _ASM_X86_HARDIRQ_H */
+3 -3
arch/x86/include/asm/idtentry.h
··· 212 212 irqentry_state_t state = irqentry_enter(regs); \ 213 213 u32 vector = (u32)(u8)error_code; \ 214 214 \ 215 + kvm_set_cpu_l1tf_flush_l1d(); \ 215 216 instrumentation_begin(); \ 216 - kvm_set_cpu_l1tf_flush_l1d(); \ 217 217 run_irq_on_irqstack_cond(__##func, regs, vector); \ 218 218 instrumentation_end(); \ 219 219 irqentry_exit(regs, state); \ ··· 250 250 \ 251 251 static __always_inline void instr_##func(struct pt_regs *regs) \ 252 252 { \ 253 - kvm_set_cpu_l1tf_flush_l1d(); \ 254 253 run_sysvec_on_irqstack_cond(__##func, regs); \ 255 254 } \ 256 255 \ ··· 257 258 { \ 258 259 irqentry_state_t state = irqentry_enter(regs); \ 259 260 \ 261 + kvm_set_cpu_l1tf_flush_l1d(); \ 260 262 instrumentation_begin(); \ 261 263 instr_##func (regs); \ 262 264 instrumentation_end(); \ ··· 288 288 static __always_inline void instr_##func(struct pt_regs *regs) \ 289 289 { \ 290 290 __irq_enter_raw(); \ 291 - kvm_set_cpu_l1tf_flush_l1d(); \ 292 291 __##func (regs); \ 293 292 __irq_exit_raw(); \ 294 293 } \ ··· 296 297 { \ 297 298 irqentry_state_t state = irqentry_enter(regs); \ 298 299 \ 300 + kvm_set_cpu_l1tf_flush_l1d(); \ 299 301 instrumentation_begin(); \ 300 302 instr_##func (regs); \ 301 303 instrumentation_end(); \