From: Maxim Levitsky <mlevitsk@redhat.com>
To: kvm@vger.kernel.org
Cc: "Andrew Jones" <drjones@redhat.com>,
"Alexandru Elisei" <alexandru.elisei@arm.com>,
"Maxim Levitsky" <mlevitsk@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Claudio Imbrenda" <imbrenda@linux.ibm.com>,
"Thomas Huth" <thuth@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Nico Boehr" <nrb@linux.ibm.com>,
"Cathy Avery" <cavery@redhat.com>,
"Janosch Frank" <frankja@linux.ibm.com>
Subject: [kvm-unit-tests PATCH v3 07/27] x86: Add test for #SMI during interrupt window
Date: Tue, 22 Nov 2022 18:11:32 +0200 [thread overview]
Message-ID: <20221122161152.293072-8-mlevitsk@redhat.com> (raw)
In-Reply-To: <20221122161152.293072-1-mlevitsk@redhat.com>
This test tests a corner case in which KVM doesn't
preserve STI interrupt shadow when #SMI arrives during it.
Due to apparent fact that STI interrupt shadow blocks real interrupts as well,
and thus prevents a vCPU kick to make the CPU enter SMM,
during the interrupt shadow, a workaround was used:
An instruction which gets VMexit anyway, but retried by
KVM is used in the interrupt shadow.
While emulating such instruction KVM doesn't reset the interrupt shadow
(because it retries it), but it can notice the pending #SMI and enter SMM,
thus the test tests that interrupt shadow in this case is preserved.
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
x86/Makefile.common | 3 +-
x86/Makefile.x86_64 | 1 +
x86/smm_int_window.c | 118 +++++++++++++++++++++++++++++++++++++++++++
x86/unittests.cfg | 5 ++
4 files changed, 126 insertions(+), 1 deletion(-)
create mode 100644 x86/smm_int_window.c
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 365e199f..698a48ab 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -87,7 +87,8 @@ tests-common = $(TEST_DIR)/vmexit.$(exe) $(TEST_DIR)/tsc.$(exe) \
$(TEST_DIR)/emulator.$(exe) \
$(TEST_DIR)/eventinj.$(exe) \
$(TEST_DIR)/smap.$(exe) \
- $(TEST_DIR)/umip.$(exe)
+ $(TEST_DIR)/umip.$(exe) \
+ $(TEST_DIR)/smm_int_window.$(exe)
# The following test cases are disabled when building EFI tests because they
# use absolute addresses in their inline assembly code, which cannot compile
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index f483dead..5d66b201 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -35,6 +35,7 @@ tests += $(TEST_DIR)/pks.$(exe)
tests += $(TEST_DIR)/pmu_lbr.$(exe)
tests += $(TEST_DIR)/pmu_pebs.$(exe)
+
ifeq ($(CONFIG_EFI),y)
tests += $(TEST_DIR)/amd_sev.$(exe)
endif
diff --git a/x86/smm_int_window.c b/x86/smm_int_window.c
new file mode 100644
index 00000000..d3a2b073
--- /dev/null
+++ b/x86/smm_int_window.c
@@ -0,0 +1,118 @@
+#include "libcflat.h"
+#include "apic.h"
+#include "processor.h"
+#include "smp.h"
+#include "isr.h"
+#include "asm/barrier.h"
+#include "alloc_page.h"
+#include "asm/page.h"
+
+#define SELF_INT_VECTOR 0xBB
+#define MEM_ALLOC_ORDER 16
+
+volatile int bad_int_received;
+volatile bool test_ended;
+volatile bool send_smi;
+
+extern unsigned long shadow_label;
+
+static void dummy_ipi_isr(isr_regs_t *regs)
+{
+ /*
+ * Test that we never get the interrupt on the instruction which
+ * is in interrupt shadow
+ */
+ if (regs->rip == (unsigned long)&shadow_label)
+ bad_int_received++;
+ eoi();
+}
+
+static void vcpu1_code(void *data)
+{
+ /*
+ * Flood vCPU0 with #SMIs
+ *
+ * Note that kvm unit tests run with seabios and its #SMI handler
+ * is only installed on vCPU0 (BSP).
+ * Sending #SMI to any other CPU will crash the guest
+ */
+ setup_vm();
+
+ while (!test_ended) {
+ if (send_smi) {
+ apic_icr_write(APIC_INT_ASSERT | APIC_DEST_PHYSICAL | APIC_DM_SMI, 0);
+ send_smi = false;
+ }
+ cpu_relax();
+ }
+}
+
+int main(void)
+{
+ int i;
+ unsigned volatile char *mem;
+
+ setup_vm();
+ cli();
+
+ mem = alloc_pages_flags(MEM_ALLOC_ORDER, AREA_ANY | FLAG_DONTZERO);
+ assert(mem);
+
+ handle_irq(SELF_INT_VECTOR, dummy_ipi_isr);
+ on_cpu_async(1, vcpu1_code, NULL);
+
+ for (i = 0 ; i < (1 << MEM_ALLOC_ORDER) && !bad_int_received ; i++) {
+
+ apic_icr_write(APIC_INT_ASSERT | APIC_DEST_PHYSICAL |
+ APIC_DM_FIXED | SELF_INT_VECTOR, 0);
+
+ /* in case the sender is still sending #SMI, wait for it*/
+ while (send_smi)
+ ;
+
+ /* ask the peer vCPU to send SMI to us */
+ send_smi = true;
+
+ /*
+ * The below memory access should never get an interrupt because
+ * it is in an interrupt shadow from the STI.
+ *
+ * Note that seems that even if a real interrupt happens, it will
+ * still not interrupt this instruction, thus vCPU kick from
+ * vCPU1, when it attempts to send #SMI to us is itself not enough,
+ * to trigger the switch to SMM mode at this point.
+
+ * Therefore STI;NOP;CLI sequence itself doesn't lead to #SMI happening
+ * in between these instructions.
+ *
+ * So instead of NOP, make an instruction that accesses a fresh memory,
+ * which will force the CPU to #VMEXIT and just before resuming the guest,
+ * KVM might notice the incoming #SMI, and enter the SMM
+ * with a still pending interrupt shadow.
+ *
+ * Also note that, just an #VMEXITing instruction like CPUID
+ * can't be used here, because KVM itself will emulate it,
+ * and clear the interrupt shadow, prior to entering the SMM.
+ *
+ * Test that in this case, the interrupt shadow is preserved,
+ * which means that upon exit from #SMI handler, the instruction
+ * should still not get the pending interrupt
+ */
+
+ asm volatile(
+ "sti\n"
+ "shadow_label:\n"
+ "movl $1, %0\n"
+ "cli\n"
+ : "=m" (*(mem+i*PAGE_SIZE))
+ ::
+ );
+ }
+
+ test_ended = 1;
+ while (cpus_active() > 1)
+ cpu_relax();
+
+ report(!bad_int_received, "No interrupts during the interrupt shadow");
+ return report_summary();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index f324e32d..e803ba03 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -478,3 +478,8 @@ file = cet.flat
arch = x86_64
smp = 2
extra_params = -enable-kvm -m 2048 -cpu host
+
+[smm_int_window]
+file = smm_int_window.flat
+smp = 2
+extra_params = -machine smm=on -machine kernel-irqchip=on -m 2g
--
2.34.3
next prev parent reply other threads:[~2022-11-22 16:15 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-22 16:11 [kvm-unit-tests PATCH v3 00/27] kvm-unit-tests: set of fixes and new tests Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 01/27] x86: replace irq_{enable|disable}() with sti()/cli() Maxim Levitsky
2022-12-01 13:46 ` Emanuele Giuseppe Esposito
2022-12-06 13:55 ` Maxim Levitsky
2022-12-06 14:15 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 02/27] x86: introduce sti_nop() and sti_nop_cli() Maxim Levitsky
2022-12-01 13:46 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 03/27] x86: add few helper functions for apic local timer Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 04/27] svm: remove nop after stgi/clgi Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 05/27] svm: make svm_intr_intercept_mix_if/gif test a bit more robust Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 06/27] svm: use apic_start_timer/apic_stop_timer instead of open coding it Maxim Levitsky
2022-11-22 16:11 ` Maxim Levitsky [this message]
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 08/27] x86: Add a simple test for SYSENTER instruction Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 09/27] svm: add simple nested shutdown test Maxim Levitsky
2022-12-01 13:46 ` Emanuele Giuseppe Esposito
2022-12-06 13:56 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 10/27] SVM: add two tests for exitintinto on exception Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 11/27] lib: Add random number generator Maxim Levitsky
2022-11-23 9:28 ` Claudio Imbrenda
2022-11-23 12:54 ` Andrew Jones
2022-12-06 13:57 ` Maxim Levitsky
2022-12-06 14:07 ` Maxim Levitsky
2022-12-14 10:33 ` Claudio Imbrenda
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 12/27] x86: add IPI stress test Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 13/27] svm: remove get_npt_pte extern Maxim Levitsky
2022-12-01 13:46 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 14/27] svm: move svm spec definitions to lib/x86/svm.h Maxim Levitsky
2022-12-01 13:54 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 15/27] svm: move some svm support functions into lib/x86/svm_lib.h Maxim Levitsky
2022-12-01 13:59 ` Emanuele Giuseppe Esposito
2022-12-06 14:10 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 16/27] svm: move setup_svm() to svm_lib.c Maxim Levitsky
2022-12-01 16:14 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 17/27] svm: correctly skip if NPT not supported Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 18/27] svm: move vmcb_ident to svm_lib.c Maxim Levitsky
2022-12-01 16:18 ` Emanuele Giuseppe Esposito
2022-12-06 14:11 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 19/27] svm: rewerite vm entry macros Maxim Levitsky
2022-12-02 10:14 ` Emanuele Giuseppe Esposito
2022-12-06 13:56 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 20/27] svm: move v2 tests run into test_run Maxim Levitsky
2022-12-02 9:53 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 21/27] svm: cleanup the default_prepare Maxim Levitsky
2022-12-02 9:45 ` Emanuele Giuseppe Esposito
2022-12-06 13:56 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 22/27] svm: introduce svm_vcpu Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 23/27] svm: introduce struct svm_test_context Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 24/27] svm: use svm_test_context in v2 tests Maxim Levitsky
2022-12-02 10:27 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 25/27] svm: move nested vcpu to test context Maxim Levitsky
2022-12-02 10:22 ` Emanuele Giuseppe Esposito
2022-12-06 14:29 ` Maxim Levitsky
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 26/27] svm: move test_guest_func " Maxim Levitsky
2022-12-02 10:28 ` Emanuele Giuseppe Esposito
2022-11-22 16:11 ` [kvm-unit-tests PATCH v3 27/27] x86: ipi_stress: add optional SVM support Maxim Levitsky
2023-06-07 23:25 ` [kvm-unit-tests PATCH v3 00/27] kvm-unit-tests: set of fixes and new tests Sean Christopherson
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=20221122161152.293072-8-mlevitsk@redhat.com \
--to=mlevitsk@redhat.com \
--cc=alex.bennee@linaro.org \
--cc=alexandru.elisei@arm.com \
--cc=cavery@redhat.com \
--cc=drjones@redhat.com \
--cc=frankja@linux.ibm.com \
--cc=imbrenda@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=nrb@linux.ibm.com \
--cc=pbonzini@redhat.com \
--cc=thuth@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox