From: Bill Wendling <morbo@google.com>
To: kvm@vger.kernel.org
Cc: oupton@google.com, pbonzini@redhat.com, drjones@redhat.com,
Jim Mattson <jmattson@google.com>,
Bill Wendling <morbo@google.com>
Subject: [kvm-unit-tests PATCH v2 5/7] x86: VMX: Add tests for monitor trap flag
Date: Wed, 26 Feb 2020 01:44:29 -0800 [thread overview]
Message-ID: <20200226094433.210968-11-morbo@google.com> (raw)
In-Reply-To: <20200226094433.210968-1-morbo@google.com>
From: Oliver Upton <oupton@google.com>
Test to verify that MTF VM-exits into host are synthesized when the
'monitor trap flag' processor-based VM-execution control is set under
various conditions.
Expect an MTF VM-exit if instruction execution produces no events other
than MTF. Should instruction execution produce a concurrent debug-trap
and MTF event, expect an MTF VM-exit with the 'pending debug exceptions'
VMCS field set. Expect an MTF VM-exit to follow event delivery should
instruction execution generate a higher-priority event, such as a
general-protection fault. Lastly, expect an MTF VM-exit to follow
delivery of a debug-trap software exception (INT1/INT3/INTO/INT n).
Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Bill Wendling <morbo@google.com>
---
x86/vmx.h | 1 +
x86/vmx_tests.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+)
diff --git a/x86/vmx.h b/x86/vmx.h
index 6214400..6adf091 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -399,6 +399,7 @@ enum Ctrl0 {
CPU_NMI_WINDOW = 1ul << 22,
CPU_IO = 1ul << 24,
CPU_IO_BITMAP = 1ul << 25,
+ CPU_MTF = 1ul << 27,
CPU_MSR_BITMAP = 1ul << 28,
CPU_MONITOR = 1ul << 29,
CPU_PAUSE = 1ul << 30,
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 1323dc5..a7abd63 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -4970,6 +4970,162 @@ static void test_vmx_preemption_timer(void)
vmcs_write(EXI_CONTROLS, saved_exit);
}
+extern unsigned char test_mtf1;
+extern unsigned char test_mtf2;
+extern unsigned char test_mtf3;
+
+__attribute__((noclone)) static void test_mtf_guest(void)
+{
+ asm ("vmcall;\n\t"
+ "out %al, $0x80;\n\t"
+ "test_mtf1:\n\t"
+ "vmcall;\n\t"
+ "out %al, $0x80;\n\t"
+ "test_mtf2:\n\t"
+ /*
+ * Prepare for the 'MOV CR3' test. Attempt to induce a
+ * general-protection fault by moving a non-canonical address into
+ * CR3. The 'MOV CR3' instruction does not take an imm64 operand,
+ * so we must MOV the desired value into a register first.
+ *
+ * MOV RAX is done before the VMCALL such that MTF is only enabled
+ * for the instruction under test.
+ */
+ "mov $0x8000000000000000, %rax;\n\t"
+ "vmcall;\n\t"
+ "mov %rax, %cr3;\n\t"
+ "test_mtf3:\n\t"
+ "vmcall;\n\t"
+ /*
+ * ICEBP/INT1 instruction. Though the instruction is now
+ * documented, don't rely on assemblers enumerating the
+ * instruction. Resort to hand assembly.
+ */
+ ".byte 0xf1;\n\t");
+}
+
+static void test_mtf_gp_handler(struct ex_regs *regs)
+{
+ regs->rip = (unsigned long) &test_mtf3;
+}
+
+static void test_mtf_db_handler(struct ex_regs *regs)
+{
+}
+
+static void enable_mtf(void)
+{
+ u32 ctrl0 = vmcs_read(CPU_EXEC_CTRL0);
+
+ vmcs_write(CPU_EXEC_CTRL0, ctrl0 | CPU_MTF);
+}
+
+static void disable_mtf(void)
+{
+ u32 ctrl0 = vmcs_read(CPU_EXEC_CTRL0);
+
+ vmcs_write(CPU_EXEC_CTRL0, ctrl0 & ~CPU_MTF);
+}
+
+static void enable_tf(void)
+{
+ unsigned long rflags = vmcs_read(GUEST_RFLAGS);
+
+ vmcs_write(GUEST_RFLAGS, rflags | X86_EFLAGS_TF);
+}
+
+static void disable_tf(void)
+{
+ unsigned long rflags = vmcs_read(GUEST_RFLAGS);
+
+ vmcs_write(GUEST_RFLAGS, rflags & ~X86_EFLAGS_TF);
+}
+
+static void report_mtf(const char *insn_name, unsigned long exp_rip)
+{
+ unsigned long rip = vmcs_read(GUEST_RIP);
+
+ assert_exit_reason(VMX_MTF);
+ report(rip == exp_rip, "MTF VM-exit after %s instruction. RIP: 0x%lx (expected 0x%lx)",
+ insn_name, rip, exp_rip);
+}
+
+static void vmx_mtf_test(void)
+{
+ unsigned long pending_dbg;
+ handler old_gp, old_db;
+
+ if (!(ctrl_cpu_rev[0].clr & CPU_MTF)) {
+ printf("CPU does not support the 'monitor trap flag' processor-based VM-execution control.\n");
+ return;
+ }
+
+ test_set_guest(test_mtf_guest);
+
+ /* Expect an MTF VM-exit after OUT instruction */
+ enter_guest();
+ skip_exit_vmcall();
+
+ enable_mtf();
+ enter_guest();
+ report_mtf("OUT", (unsigned long) &test_mtf1);
+ disable_mtf();
+
+ /*
+ * Concurrent #DB trap and MTF on instruction boundary. Expect MTF
+ * VM-exit with populated 'pending debug exceptions' VMCS field.
+ */
+ enter_guest();
+ skip_exit_vmcall();
+
+ enable_mtf();
+ enable_tf();
+
+ enter_guest();
+ report_mtf("OUT", (unsigned long) &test_mtf2);
+ pending_dbg = vmcs_read(GUEST_PENDING_DEBUG);
+ report(pending_dbg & DR_STEP,
+ "'pending debug exceptions' field after MTF VM-exit: 0x%lx (expected 0x%lx)",
+ pending_dbg, (unsigned long) DR_STEP);
+
+ disable_mtf();
+ disable_tf();
+ vmcs_write(GUEST_PENDING_DEBUG, 0);
+
+ /*
+ * #GP exception takes priority over MTF. Expect MTF VM-exit with RIP
+ * advanced to first instruction of #GP handler.
+ */
+ enter_guest();
+ skip_exit_vmcall();
+
+ old_gp = handle_exception(GP_VECTOR, test_mtf_gp_handler);
+
+ enable_mtf();
+ enter_guest();
+ report_mtf("MOV CR3", (unsigned long) get_idt_addr(&boot_idt[GP_VECTOR]));
+ disable_mtf();
+
+ /*
+ * Concurrent MTF and privileged software exception (i.e. ICEBP/INT1).
+ * MTF should follow the delivery of #DB trap, though the SDM doesn't
+ * provide clear indication of the relative priority.
+ */
+ enter_guest();
+ skip_exit_vmcall();
+
+ handle_exception(GP_VECTOR, old_gp);
+ old_db = handle_exception(DB_VECTOR, test_mtf_db_handler);
+
+ enable_mtf();
+ enter_guest();
+ report_mtf("INT1", (unsigned long) get_idt_addr(&boot_idt[DB_VECTOR]));
+ disable_mtf();
+
+ enter_guest();
+ handle_exception(DB_VECTOR, old_db);
+}
+
/*
* Tests for VM-execution control fields
*/
@@ -9505,5 +9661,6 @@ struct vmx_test vmx_tests[] = {
TEST(atomic_switch_max_msrs_test),
TEST(atomic_switch_overflow_msrs_test),
TEST(rdtsc_vmexit_diff_test),
+ TEST(vmx_mtf_test),
{ NULL, NULL, NULL, NULL, NULL, {0} },
};
--
2.25.0.265.gbab2e86ba0-goog
next prev parent reply other threads:[~2020-02-26 9:45 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-26 7:44 [kvm-unit-tests PATCH 0/7] Fixes for clang builds morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 1/7] x86: emulator: use "SSE2" for the target morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 2/7] pci: use uint32_t for unsigned long values morbo
2020-02-26 7:59 ` Andrew Jones
2020-02-26 9:02 ` Bill Wendling
2020-02-26 9:24 ` Andrew Jones
2020-02-26 7:44 ` [kvm-unit-tests PATCH 3/7] x86: realmode: syscall: add explicit size suffix to ambiguous instructions morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 4/7] svm: change operand to output-only for matching constraint morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 5/7] svm: convert neg shift to unsigned shift morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 6/7] x86: VMX: use inline asm to get stack pointer morbo
2020-02-26 7:44 ` [kvm-unit-tests PATCH 7/7] x86: VMX: the "noclone" attribute is gcc-specific morbo
2020-02-26 8:21 ` Oliver Upton
2020-02-26 8:22 ` Oliver Upton
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 0/7] Fixes for clang builds Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 1/7] x86: emulator: use "SSE2" for the target Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 1/7] x86: pmu: Test WRMSR on a running counter Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 2/7] pci: use uint32_t for unsigned long values Bill Wendling
2020-02-28 11:04 ` Paolo Bonzini
2020-02-28 12:46 ` Andrew Jones
2020-02-28 13:02 ` Paolo Bonzini
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 2/7] x86: provide enabled and disabled variation of the PCID test Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 3/7] x86: pmu: Test perfctr overflow after WRMSR on a running counter Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 3/7] x86: realmode: syscall: add explicit size suffix to ambiguous instructions Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 4/7] svm: change operand to output-only for matching constraint Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 4/7] vmx: tweak XFAILS for #DB test Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 5/7] svm: convert neg shift to unsigned shift Bill Wendling
2020-02-28 11:12 ` Paolo Bonzini
2020-02-26 9:44 ` Bill Wendling [this message]
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 6/7] x86: emulator: use "SSE2" for the target Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 6/7] x86: VMX: use inline asm to get stack pointer Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH v2 7/7] pci: cast masks to uint32_t for unsigned long values Bill Wendling
2020-02-26 9:44 ` [kvm-unit-tests PATCH 7/7] x86: VMX: the "noclone" attribute is gcc-specific Bill Wendling
2020-02-28 11:16 ` Paolo Bonzini
2020-02-28 18:19 ` Oliver Upton
2020-02-28 18:24 ` Paolo Bonzini
2020-02-28 18:40 ` Oliver Upton
2020-02-26 19:02 ` [kvm-unit-tests PATCH v2 0/7] Fixes for clang builds Oliver Upton
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 " Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 1/7] x86: emulator: use "SSE2" for the target Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 2/7] pci: cast masks to uint32_t for unsigned long values Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 3/7] x86: realmode: syscall: add explicit size suffix to ambiguous instructions Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 4/7] svm: change operand to output-only for matching constraint Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 5/7] svm: convert neg shift to unsigned shift Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 6/7] x86: VMX: use inline asm to get stack pointer Bill Wendling
2020-02-26 20:12 ` [kvm-unit-tests PATCH v3 7/7] x86: VMX: the "noclone" attribute is gcc-specific Bill Wendling
2020-02-27 2:05 ` Oliver Upton
2020-02-28 11:19 ` [kvm-unit-tests PATCH v2 0/7] Fixes for clang builds Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200226094433.210968-11-morbo@google.com \
--to=morbo@google.com \
--cc=drjones@redhat.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=oupton@google.com \
--cc=pbonzini@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.