Skip to content

Commit 983820c

Browse files
committed
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>
1 parent 7803339 commit 983820c

File tree

7 files changed

+51
-14
lines changed

7 files changed

+51
-14
lines changed

tools/testing/selftests/kvm/include/x86/processor.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,46 @@ static inline void kvm_hypercall_map_gpa_range(uint64_t gpa, uint64_t size,
13351335
GUEST_ASSERT(!ret);
13361336
}
13371337

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+
13381378
void __vm_xsave_require_permission(uint64_t xfeature, const char *name);
13391379

13401380
#define vm_xsave_require_permission(xfeature) \

tools/testing/selftests/kvm/x86/hyperv_ipi.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ static void receiver_code(void *hcall_page, vm_vaddr_t pgs_gpa)
6363
/* Signal sender vCPU we're ready */
6464
ipis_rcvd[vcpu_id] = (u64)-1;
6565

66-
for (;;)
67-
asm volatile("sti; hlt; cli");
66+
for (;;) {
67+
safe_halt();
68+
cli();
69+
}
6870
}
6971

7072
static void guest_ipi_handler(struct ex_regs *regs)

tools/testing/selftests/kvm/x86/svm_int_ctl_test.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ static void l2_guest_code(struct svm_test_data *svm)
4242
x2apic_write_reg(APIC_ICR,
4343
APIC_DEST_SELF | APIC_INT_ASSERT | INTR_IRQ_NUMBER);
4444

45-
__asm__ __volatile__(
46-
"sti\n"
47-
"nop\n"
48-
);
45+
sti_nop();
4946

5047
GUEST_ASSERT(vintr_irq_called);
5148
GUEST_ASSERT(intr_irq_called);

tools/testing/selftests/kvm/x86/ucna_injection_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static void ucna_injection_guest_code(void)
8686
wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_CMCI_EN);
8787

8888
/* Enables interrupt in guest. */
89-
asm volatile("sti");
89+
sti();
9090

9191
/* Let user space inject the first UCNA */
9292
GUEST_SYNC(SYNC_FIRST_UCNA);

tools/testing/selftests/kvm/x86/xapic_ipi_test.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ static void halter_guest_code(struct test_data_page *data)
106106
data->halter_tpr = xapic_read_reg(APIC_TASKPRI);
107107
data->halter_ppr = xapic_read_reg(APIC_PROCPRI);
108108
data->hlt_count++;
109-
asm volatile("sti; hlt; cli");
109+
safe_halt();
110+
cli();
110111
data->wake_count++;
111112
}
112113
}

tools/testing/selftests/kvm/x86/xapic_state_test.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct xapic_vcpu {
1818

1919
static void xapic_guest_code(void)
2020
{
21-
asm volatile("cli");
21+
cli();
2222

2323
xapic_enable();
2424

@@ -38,7 +38,7 @@ static void xapic_guest_code(void)
3838

3939
static void x2apic_guest_code(void)
4040
{
41-
asm volatile("cli");
41+
cli();
4242

4343
x2apic_enable();
4444

tools/testing/selftests/kvm/x86/xen_shinfo_test.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,7 @@ static void guest_code(void)
191191
struct vcpu_runstate_info *rs = (void *)RUNSTATE_VADDR;
192192
int i;
193193

194-
__asm__ __volatile__(
195-
"sti\n"
196-
"nop\n"
197-
);
194+
sti_nop();
198195

199196
/* Trigger an interrupt injection */
200197
GUEST_SYNC(TEST_INJECT_VECTOR);

0 commit comments

Comments
 (0)