[kvm-unit-tests PATCH] x86/emulator: Test POP-SS blocking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Verify that CPU interruptibility due to POP SS is set correctly (and #DB
is suppressed).

Signed-off-by: Michal Luczaj <mhal@xxxxxxx>
---
Initially I wanted to test #DB suppression with EFLAGS.TF=1, but it
turned out that making the emulator set ctxt->interruptibility like this

	asm volatile("pushf\n\t"
		     "push %[flags]\n\t"
		     "popf\n\t"
		     KVM_FEP "mov %[ss], %%ss\n\t"
		     "popf"
		     :
		     : [ss] "r" (read_ss()),
		       [flags] "r" (read_rflags() | X86_EFLAGS_TF)
		     : "memory");

results in "KVM: entry failed, hardware error 0x80000021".
kvm_intel.dump_invalid_vmcs=1 tells me at that moment

Interruptibility = 00000002
DebugExceptions = 0x0000000000000000

so perhaps it's related to the problem described in
https://lkml.kernel.org/kvm/20220120000624.655815-1-seanjc@xxxxxxxxxx/ ?
That said, I don't know if combining FEP+blocking+TF+DB is a misuse on
my side, a bug, or a detail that happens to be unimplemented.

Anyway, the POP-SS blocking test avoids touching EFLAGS.TF by using
DR0/7.

Note that doing this the ASM_TRY() way would require extending
setup_idt() (to handle #DB) and introducing another ASM_TRY() variant
(one without the initial `movl $0, %%gs:4`).

 x86/Makefile.i386 |  3 ++-
 x86/popss.c       | 59 +++++++++++++++++++++++++++++++++++++++++++++++
 x86/unittests.cfg |  4 ++++
 3 files changed, 65 insertions(+), 1 deletion(-)
 create mode 100644 x86/popss.c

diff --git a/x86/Makefile.i386 b/x86/Makefile.i386
index 0a845e6..b570ae2 100644
--- a/x86/Makefile.i386
+++ b/x86/Makefile.i386
@@ -9,6 +9,7 @@ arch_LDFLAGS = -m elf_i386
 cflatobjs += lib/x86/setjmp32.o lib/ldiv32.o
 
 tests = $(TEST_DIR)/taskswitch.$(exe) $(TEST_DIR)/taskswitch2.$(exe) \
-	$(TEST_DIR)/cmpxchg8b.$(exe) $(TEST_DIR)/la57.$(exe)
+	$(TEST_DIR)/cmpxchg8b.$(exe) $(TEST_DIR)/la57.$(exe) \
+	$(TEST_DIR)/popss.$(exe)
 
 include $(SRCDIR)/$(TEST_DIR)/Makefile.common
diff --git a/x86/popss.c b/x86/popss.c
new file mode 100644
index 0000000..7201f1e
--- /dev/null
+++ b/x86/popss.c
@@ -0,0 +1,59 @@
+#include <asm/debugreg.h>
+
+#include "processor.h"
+#include "libcflat.h"
+#include "vmalloc.h"
+#include "desc.h"
+
+static void test_pop_ss_blocking_handler(struct ex_regs *regs)
+{
+	extern char test_pop_ss_blocking_cont;
+
+	regs->rip = (ulong)&test_pop_ss_blocking_cont;
+}
+
+static void test_pop_ss_blocking(void)
+{
+	extern char db_blocked;
+	int success = 0;
+	handler old;
+
+	old = handle_exception(DB_VECTOR, test_pop_ss_blocking_handler);
+
+	write_dr0(&db_blocked);
+	write_dr7(DR7_FIXED_1 |
+		  DR7_GLOBAL_ENABLE_DRx(0) |
+		  DR7_EXECUTE_DRx(0) |
+		  DR7_LEN_1_DRx(0));
+
+	/*
+	 * The idea is that #DB on the instruction following POP SS should be
+	 * suppressed. If the exception is actually suppressed, `success` gets
+	 * set to 1, otherwise exception handler advances RIP away.
+	 */
+	asm volatile("push %[ss]\n\t"
+		     KVM_FEP "pop %%ss\n\t"
+		     "db_blocked: mov $1, %[success]\n\t"
+		     "test_pop_ss_blocking_cont:"
+		     : [success] "+g" (success)
+		     : [ss] "r" (read_ss())
+		     : "memory");
+
+	write_dr7(DR7_FIXED_1);
+	handle_exception(DB_VECTOR, old);
+
+	report(success, "#DB suppressed after POP SS");
+}
+
+int main(void)
+{
+	setup_vm();
+
+	if (is_fep_available())
+		test_pop_ss_blocking();
+	else
+		report_skip("skipping POP-SS blocking test, "
+			    "use kvm.force_emulation_prefix=1 to enable");
+
+	return report_summary();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index ed65185..8d4e917 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -305,6 +305,10 @@ extra_params = -cpu qemu64,+umip
 file = la57.flat
 arch = i386
 
+[popss]
+file = popss.flat
+arch = i386
+
 [vmx]
 file = vmx.flat
 extra_params = -cpu max,+vmx -append "-exit_monitor_from_l2_test -ept_access* -vmx_smp* -vmx_vmcs_shadow_test -atomic_switch_overflow_msrs_test -vmx_init_signal_test -vmx_apic_passthrough_tpr_threshold_test -apic_reg_virt_test -virt_x2apic_mode_test -vmx_pf_exception_test -vmx_pf_no_vpid_test -vmx_pf_invvpid_test -vmx_pf_vpid_test"
-- 
2.37.2




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux