From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paolo Bonzini Subject: [PATCH kvm-unit-tests] x86: add SMM tests Date: Fri, 27 May 2016 14:14:32 +0200 Message-ID: <1464351272-7377-1-git-send-email-pbonzini@redhat.com> To: kvm@vger.kernel.org Return-path: Received: from mail-wm0-f67.google.com ([74.125.82.67]:34890 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751150AbcE0MOi (ORCPT ); Fri, 27 May 2016 08:14:38 -0400 Received: by mail-wm0-f67.google.com with SMTP id e3so14314080wme.2 for ; Fri, 27 May 2016 05:14:37 -0700 (PDT) Received: from 640k.lan (94-39-188-118.adsl-ull.clienti.tiscali.it. [94.39.188.118]) by smtp.gmail.com with ESMTPSA id c62sm8321015wmd.1.2016.05.27.05.14.34 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 27 May 2016 05:14:35 -0700 (PDT) Sender: kvm-owner@vger.kernel.org List-ID: Add a generic speed test for SMIs and a testcase for https://github.com/tianocore/edk2/issues/91. Signed-off-by: Paolo Bonzini --- x86/Makefile.common | 1 + x86/smm_eventinj.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ x86/unittests.cfg | 4 +++ x86/vmexit.c | 6 ++++ 4 files changed, 94 insertions(+) create mode 100644 x86/smm_eventinj.c diff --git a/x86/Makefile.common b/x86/Makefile.common index 55e6cde..a04f14a 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -45,6 +45,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ + $(TEST_DIR)/smm_eventinj.flat ifdef API tests-common += api/api-sample diff --git a/x86/smm_eventinj.c b/x86/smm_eventinj.c new file mode 100644 index 0000000..1029289 --- /dev/null +++ b/x86/smm_eventinj.c @@ -0,0 +1,83 @@ +#include "libcflat.h" +#include "smp.h" +#include "processor.h" +#include "x86/desc.h" +#include "x86/apic.h" +#include "x86/io.h" + +/* Provoke race between interrupt injection and SMM entry, causing a + * failed vmentry because IF=0 but VM_ENTRY_INTR_INFO_FIELD[31]=1. + */ + +#define MY_IRQ_PIN 0x0e +#define MY_IRQ_VEC 0x21 + +static volatile int stopped; + +static void set_irq_line(unsigned line, int val) +{ + outb(val, 0x2000 + line); +} + +static void set_ioapic_redir(unsigned line, unsigned vec) +{ + /* Edge triggered, CPU 0 */ + ioapic_redir_entry_t e = { + .vector = vec, + }; + + ioapic_write_redir(line, e); +} + +static void ipi(void *x) +{ + while (!stopped) { + int i = 0; + for (i = 0; i < 1000000; i++) asm("pause"); + + set_irq_line(MY_IRQ_PIN, 1); + apic_icr_write(APIC_DM_SMI|APIC_INT_ASSERT, 0); + set_irq_line(MY_IRQ_PIN, 0); + } +} + +extern void dummy(void); +asm("dummy: \n" + "call eoi\n" +#ifndef __x86_64__ + "iret" +#else + "iretq" +#endif + ); + +int main(int ac, char **av) +{ + int i; + + smp_init(); + mask_pic_interrupts(); + + set_ioapic_redir(MY_IRQ_PIN, MY_IRQ_VEC); + set_idt_entry(MY_IRQ_VEC, dummy, 0); + if (cpu_count() < 2) { + printf("SMP needed for this test\n"); + exit(1); + } + + /* Because we use the APIC to inject SMIs, ensure SeaBIOS doesn't find + * a valid "SMM command" in port 0xb2. If it does, it peeks at the + * registers to get the other parameters, and who knows what happens + * then. + */ + outb(42, 0xb2); + + printf("starting IPI thread\n"); + on_cpu_async(1, ipi, 0); + printf("starting HLT loop\n"); + asm("sti"); + for (i = 0; i < 150; i++) + asm("hlt"); + stopped = 1; + return 0; +} diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 61a4d24..6ba11fb 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -188,6 +188,10 @@ arch = x86_64 file = debug.flat arch = x86_64 +[smm_eventinj] +file = smm_eventinj.flat +smp = 2 + [hyperv_synic] file = hyperv_synic.flat smp = 2 diff --git a/x86/vmexit.c b/x86/vmexit.c index 9e04975..f21d054 100644 --- a/x86/vmexit.c +++ b/x86/vmexit.c @@ -134,6 +134,11 @@ static void wr_tsc_adjust_msr(void) wrmsr(MSR_TSC_ADJUST, 0x0); } +static void smi_outb(void) +{ + outb(42, 0xb2); +} + static struct pci_test { unsigned iobar; unsigned ioport; @@ -287,6 +292,7 @@ static struct test tests[] = { { ple_round_robin, "ple-round-robin", .parallel = 1 }, { wr_tsc_adjust_msr, "wr_tsc_adjust_msr", .parallel = 1 }, { rd_tsc_adjust_msr, "rd_tsc_adjust_msr", .parallel = 1 }, + { smi_outb, "smi_outb", .parallel = 0 }, { NULL, "pci-mem", .parallel = 0, .next = pci_mem_next }, { NULL, "pci-io", .parallel = 0, .next = pci_io_next }, }; -- 1.8.3.1