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

KVM: selftests: Add helpers for locally (un)blocking IRQs on x86

Copy KVM-Unit-Tests' x86 helpers for emitting STI and CLI, comments and
all, and use them throughout x86 selftests. The safe_halt() and sti_nop()
logic in particular benefits from centralized comments, as the behavior
isn't obvious unless the reader is already aware of the STI shadow.

Cc: Manali Shukla <Manali.Shukla@amd.com>
Link: https://lore.kernel.org/r/20241220012617.3513898-1-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+51 -14
+40
tools/testing/selftests/kvm/include/x86/processor.h
··· 1335 1335 GUEST_ASSERT(!ret); 1336 1336 } 1337 1337 1338 + /* 1339 + * Execute HLT in an STI interrupt shadow to ensure that a pending IRQ that's 1340 + * intended to be a wake event arrives *after* HLT is executed. Modern CPUs, 1341 + * except for a few oddballs that KVM is unlikely to run on, block IRQs for one 1342 + * instruction after STI, *if* RFLAGS.IF=0 before STI. Note, Intel CPUs may 1343 + * block other events beyond regular IRQs, e.g. may block NMIs and SMIs too. 1344 + */ 1345 + static inline void safe_halt(void) 1346 + { 1347 + asm volatile("sti; hlt"); 1348 + } 1349 + 1350 + /* 1351 + * Enable interrupts and ensure that interrupts are evaluated upon return from 1352 + * this function, i.e. execute a nop to consume the STi interrupt shadow. 1353 + */ 1354 + static inline void sti_nop(void) 1355 + { 1356 + asm volatile ("sti; nop"); 1357 + } 1358 + 1359 + /* 1360 + * Enable interrupts for one instruction (nop), to allow the CPU to process all 1361 + * interrupts that are already pending. 1362 + */ 1363 + static inline void sti_nop_cli(void) 1364 + { 1365 + asm volatile ("sti; nop; cli"); 1366 + } 1367 + 1368 + static inline void sti(void) 1369 + { 1370 + asm volatile("sti"); 1371 + } 1372 + 1373 + static inline void cli(void) 1374 + { 1375 + asm volatile ("cli"); 1376 + } 1377 + 1338 1378 void __vm_xsave_require_permission(uint64_t xfeature, const char *name); 1339 1379 1340 1380 #define vm_xsave_require_permission(xfeature) \
+4 -2
tools/testing/selftests/kvm/x86/hyperv_ipi.c
··· 63 63 /* Signal sender vCPU we're ready */ 64 64 ipis_rcvd[vcpu_id] = (u64)-1; 65 65 66 - for (;;) 67 - asm volatile("sti; hlt; cli"); 66 + for (;;) { 67 + safe_halt(); 68 + cli(); 69 + } 68 70 } 69 71 70 72 static void guest_ipi_handler(struct ex_regs *regs)
+1 -4
tools/testing/selftests/kvm/x86/svm_int_ctl_test.c
··· 42 42 x2apic_write_reg(APIC_ICR, 43 43 APIC_DEST_SELF | APIC_INT_ASSERT | INTR_IRQ_NUMBER); 44 44 45 - __asm__ __volatile__( 46 - "sti\n" 47 - "nop\n" 48 - ); 45 + sti_nop(); 49 46 50 47 GUEST_ASSERT(vintr_irq_called); 51 48 GUEST_ASSERT(intr_irq_called);
+1 -1
tools/testing/selftests/kvm/x86/ucna_injection_test.c
··· 86 86 wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_CMCI_EN); 87 87 88 88 /* Enables interrupt in guest. */ 89 - asm volatile("sti"); 89 + sti(); 90 90 91 91 /* Let user space inject the first UCNA */ 92 92 GUEST_SYNC(SYNC_FIRST_UCNA);
+2 -1
tools/testing/selftests/kvm/x86/xapic_ipi_test.c
··· 106 106 data->halter_tpr = xapic_read_reg(APIC_TASKPRI); 107 107 data->halter_ppr = xapic_read_reg(APIC_PROCPRI); 108 108 data->hlt_count++; 109 - asm volatile("sti; hlt; cli"); 109 + safe_halt(); 110 + cli(); 110 111 data->wake_count++; 111 112 } 112 113 }
+2 -2
tools/testing/selftests/kvm/x86/xapic_state_test.c
··· 18 18 19 19 static void xapic_guest_code(void) 20 20 { 21 - asm volatile("cli"); 21 + cli(); 22 22 23 23 xapic_enable(); 24 24 ··· 38 38 39 39 static void x2apic_guest_code(void) 40 40 { 41 - asm volatile("cli"); 41 + cli(); 42 42 43 43 x2apic_enable(); 44 44
+1 -4
tools/testing/selftests/kvm/x86/xen_shinfo_test.c
··· 191 191 struct vcpu_runstate_info *rs = (void *)RUNSTATE_VADDR; 192 192 int i; 193 193 194 - __asm__ __volatile__( 195 - "sti\n" 196 - "nop\n" 197 - ); 194 + sti_nop(); 198 195 199 196 /* Trigger an interrupt injection */ 200 197 GUEST_SYNC(TEST_INJECT_VECTOR);