Commit 983820cb authored by Sean Christopherson's avatar Sean Christopherson
Browse files

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: default avatarSean Christopherson <seanjc@google.com>
parent 7803339f
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -1335,6 +1335,46 @@ static inline void kvm_hypercall_map_gpa_range(uint64_t gpa, uint64_t size,
	GUEST_ASSERT(!ret);
}

/*
 * Execute HLT in an STI interrupt shadow to ensure that a pending IRQ that's
 * intended to be a wake event arrives *after* HLT is executed.  Modern CPUs,
 * except for a few oddballs that KVM is unlikely to run on, block IRQs for one
 * instruction after STI, *if* RFLAGS.IF=0 before STI.  Note, Intel CPUs may
 * block other events beyond regular IRQs, e.g. may block NMIs and SMIs too.
 */
static inline void safe_halt(void)
{
	asm volatile("sti; hlt");
}

/*
 * Enable interrupts and ensure that interrupts are evaluated upon return from
 * this function, i.e. execute a nop to consume the STi interrupt shadow.
 */
static inline void sti_nop(void)
{
	asm volatile ("sti; nop");
}

/*
 * Enable interrupts for one instruction (nop), to allow the CPU to process all
 * interrupts that are already pending.
 */
static inline void sti_nop_cli(void)
{
	asm volatile ("sti; nop; cli");
}

static inline void sti(void)
{
	asm volatile("sti");
}

static inline void cli(void)
{
	asm volatile ("cli");
}

void __vm_xsave_require_permission(uint64_t xfeature, const char *name);

#define vm_xsave_require_permission(xfeature)	\
+4 −2
Original line number Diff line number Diff line
@@ -63,8 +63,10 @@ static void receiver_code(void *hcall_page, vm_vaddr_t pgs_gpa)
	/* Signal sender vCPU we're ready */
	ipis_rcvd[vcpu_id] = (u64)-1;

	for (;;)
		asm volatile("sti; hlt; cli");
	for (;;) {
		safe_halt();
		cli();
	}
}

static void guest_ipi_handler(struct ex_regs *regs)
+1 −4
Original line number Diff line number Diff line
@@ -42,10 +42,7 @@ static void l2_guest_code(struct svm_test_data *svm)
	x2apic_write_reg(APIC_ICR,
		APIC_DEST_SELF | APIC_INT_ASSERT | INTR_IRQ_NUMBER);

	__asm__ __volatile__(
		"sti\n"
		"nop\n"
	);
	sti_nop();

	GUEST_ASSERT(vintr_irq_called);
	GUEST_ASSERT(intr_irq_called);
+1 −1
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ static void ucna_injection_guest_code(void)
	wrmsr(MSR_IA32_MCx_CTL2(UCNA_BANK), ctl2 | MCI_CTL2_CMCI_EN);

	/* Enables interrupt in guest. */
	asm volatile("sti");
	sti();

	/* Let user space inject the first UCNA */
	GUEST_SYNC(SYNC_FIRST_UCNA);
+2 −1
Original line number Diff line number Diff line
@@ -106,7 +106,8 @@ static void halter_guest_code(struct test_data_page *data)
		data->halter_tpr = xapic_read_reg(APIC_TASKPRI);
		data->halter_ppr = xapic_read_reg(APIC_PROCPRI);
		data->hlt_count++;
		asm volatile("sti; hlt; cli");
		safe_halt();
		cli();
		data->wake_count++;
	}
}
Loading