@@ -669,6 +669,26 @@ static inline void sti(void)
asm volatile ("sti");
}
+
+/*
+ * Enable interrupts and ensure that interrupts are evaluated upon
+ * return from this function.
+ */
+static inline void sti_nop(void)
+{
+ asm volatile ("sti; nop");
+}
+
+
+/*
+ * Enable interrupts for one cpu cycle, allowing the CPU
+ * to process all interrupts that are already pending.
+ */
+static inline void sti_nop_cli(void)
+{
+ asm volatile ("sti; nop; cli");
+}
+
static inline unsigned long long rdrand(void)
{
long long r;
@@ -313,7 +313,7 @@ static void test_self_ipi_x2apic(void)
volatile int nmi_counter_private, nmi_counter, nmi_hlt_counter, sti_loop_active;
-static void sti_nop(char *p)
+static void test_sti_nop(char *p)
{
asm volatile (
".globl post_sti \n\t"
@@ -335,7 +335,7 @@ static void sti_loop(void *ignore)
unsigned k = 0;
while (sti_loop_active)
- sti_nop((char *)(ulong)((k++ * 4096) % (128 * 1024 * 1024)));
+ test_sti_nop((char *)(ulong)((k++ * 4096) % (128 * 1024 * 1024)));
}
static void nmi_handler(isr_regs_t *regs)
@@ -294,9 +294,7 @@ int main(void)
apic_self_ipi(32);
apic_self_ipi(33);
io_delay();
- sti();
- asm volatile("nop");
- cli();
+ sti_nop_cli();
printf("After vec 32 and 33 to self\n");
report(test_count == 2, "vec 32/33");
@@ -353,9 +351,7 @@ int main(void)
/* this is needed on VMX without NMI window notification.
Interrupt windows is used instead, so let pending NMI
to be injected */
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
report(test_count == 2, "NMI");
/* generate NMI that will fault on IRET */
@@ -367,9 +363,7 @@ int main(void)
/* this is needed on VMX without NMI window notification.
Interrupt windows is used instead, so let pending NMI
to be injected */
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
printf("After NMI to self\n");
report(test_count == 2, "NMI");
stack_phys = (ulong)virt_to_phys(alloc_page());
@@ -128,8 +128,7 @@ static void test_ioapic_simultaneous(void)
cli();
toggle_irq_line(0x0f);
toggle_irq_line(0x0e);
- sti();
- asm volatile ("nop");
+ sti_nop();
report(g_66 && g_78 && g_66_after_78 && g_66_rip == g_78_rip,
"ioapic simultaneous edge interrupts");
}
@@ -1000,9 +1000,7 @@ static bool pending_event_finished(struct svm_test *test)
return true;
}
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (!pending_event_ipi_fired) {
report_fail("Pending interrupt not dispatched after IRQ enabled\n");
@@ -1056,9 +1054,7 @@ static void pending_event_cli_test(struct svm_test *test)
}
/* VINTR_MASKING is zero. This should cause the IPI to fire. */
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (pending_event_ipi_fired != true) {
set_test_stage(test, -1);
@@ -1072,9 +1068,7 @@ static void pending_event_cli_test(struct svm_test *test)
* the VINTR interception should be clear in VMCB02. Check
* that L0 did not leave a stale VINTR in the VMCB.
*/
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
}
static bool pending_event_cli_finished(struct svm_test *test)
@@ -1105,9 +1099,7 @@ static bool pending_event_cli_finished(struct svm_test *test)
return true;
}
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (pending_event_ipi_fired != true) {
report_fail("Interrupt not triggered by host");
@@ -1243,9 +1235,7 @@ static bool interrupt_finished(struct svm_test *test)
return true;
}
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR);
vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK;
@@ -1540,9 +1530,7 @@ static void virq_inject_test(struct svm_test *test)
vmmcall();
}
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (!virq_fired) {
report_fail("virtual interrupt not fired after L2 sti");
@@ -1557,9 +1545,7 @@ static void virq_inject_test(struct svm_test *test)
vmmcall();
}
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (!virq_fired) {
report_fail("virtual interrupt not fired after return from VINTR intercept");
@@ -1568,9 +1554,7 @@ static void virq_inject_test(struct svm_test *test)
vmmcall();
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (virq_fired) {
report_fail("virtual interrupt fired when V_IRQ_PRIO less than V_TPR");
@@ -1739,9 +1723,7 @@ static bool reg_corruption_finished(struct svm_test *test)
void* guest_rip = (void*)vmcb->save.rip;
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
if (guest_rip == insb_instruction_label && io_port_var != 0xAA) {
report_fail("RIP corruption detected after %d timer interrupts",
@@ -3049,8 +3031,7 @@ static void svm_intr_intercept_mix_if_guest(struct svm_test *test)
{
asm volatile("nop;nop;nop;nop");
report(!dummy_isr_recevied, "No interrupt expected");
- sti();
- asm volatile("nop");
+ sti_nop();
report(0, "must not reach here");
}
@@ -3080,8 +3061,7 @@ static void svm_intr_intercept_mix_gif_guest(struct svm_test *test)
// clear GIF and enable IF
// that should still not cause VM exit
clgi();
- sti();
- asm volatile("nop");
+ sti_nop();
report(!dummy_isr_recevied, "No interrupt expected");
stgi();
@@ -3142,8 +3122,7 @@ static void svm_intr_intercept_mix_nmi_guest(struct svm_test *test)
clgi();
asm volatile("nop");
apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI, 0);
- sti(); // should have no effect
- asm volatile("nop");
+ sti_nop(); // should have no effect
report(!nmi_recevied, "No NMI expected");
stgi();
@@ -3173,8 +3152,7 @@ static void svm_intr_intercept_mix_smi_guest(struct svm_test *test)
clgi();
asm volatile("nop");
apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_SMI, 0);
- sti(); // should have no effect
- asm volatile("nop");
+ sti_nop(); // should have no effect
stgi();
asm volatile("nop");
report(0, "must not reach here");
@@ -1625,8 +1625,7 @@ static void interrupt_main(void)
start = rdtsc();
apic_write(APIC_TMICT, 1000000);
- sti();
- asm volatile ("nop");
+ sti_nop();
vmcall();
report(rdtsc() - start > 10000 && timer_fired,
@@ -1639,8 +1638,7 @@ static void interrupt_main(void)
start = rdtsc();
apic_write(APIC_TMICT, 1000000);
- sti();
- asm volatile ("nop");
+ sti_nop();
vmcall();
report(rdtsc() - start > 10000 && timer_fired,
@@ -1709,9 +1707,7 @@ static int interrupt_exit_handler(union exit_reason exit_reason)
int vector = vmcs_read(EXI_INTR_INFO) & 0xff;
handle_external_interrupt(vector);
} else {
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
}
if (vmx_get_test_stage() >= 2)
vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE);
@@ -6716,9 +6712,7 @@ static void test_x2apic_wr(
assert_exit_reason(exit_reason_want);
/* Clear the external interrupt. */
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
report(handle_x2apic_ipi_ran,
"Got pending interrupt after IRQ enabled.");
@@ -8414,9 +8408,7 @@ static void vmx_pending_event_test_core(bool guest_hlt)
report(!vmx_pending_event_guest_run,
"Guest did not run before host received IPI");
- sti();
- asm volatile ("nop");
- cli();
+ sti_nop_cli();
report(vmx_pending_event_ipi_fired,
"Got pending interrupt after IRQ enabled");
@@ -9397,7 +9389,7 @@ static void vmx_hlt_with_rvi_guest(void)
{
handle_irq(HLT_WITH_RVI_VECTOR, vmx_hlt_with_rvi_guest_isr);
- sti();
+ sti_nop();
asm volatile ("nop");
vmcall();
@@ -9557,8 +9549,7 @@ static void vmx_apic_passthrough_tpr_threshold_test(void)
/* Clean pending self-IPI */
vmx_apic_passthrough_tpr_threshold_ipi_isr_fired = false;
handle_irq(ipi_vector, vmx_apic_passthrough_tpr_threshold_ipi_isr);
- sti();
- asm volatile ("nop");
+ sti_nop();
report(vmx_apic_passthrough_tpr_threshold_ipi_isr_fired, "self-IPI fired");
report_pass(__func__);
Add functions that shorten the common usage of sti Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> --- lib/x86/processor.h | 20 +++++++++++++++++++ x86/apic.c | 4 ++-- x86/eventinj.c | 12 +++--------- x86/ioapic.c | 3 +-- x86/svm_tests.c | 48 ++++++++++++--------------------------------- x86/vmx_tests.c | 23 +++++++--------------- 6 files changed, 46 insertions(+), 64 deletions(-)