All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Boqun Feng (Intel)" <boqun.feng@gmail.com>
To: xen-devel@lists.xen.org
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	"Boqun Feng (Intel)" <boqun.feng@gmail.com>,
	yu.c.zhang@linux.intel.com, Jan Beulich <jbeulich@suse.com>
Subject: [PATCH XTF v3] Functional: Add a UMIP test
Date: Tue, 15 Aug 2017 11:18:20 +0800	[thread overview]
Message-ID: <20170815031820.20234-1-boqun.feng@gmail.com> (raw)

Add a "umip" test for the User-Model Instruction Prevention. The test
simply tries to run sgdt/sidt/sldt/str/smsw in guest user-mode with
CR4_UMIP = 1.

Signed-off-by: Boqun Feng (Intel) <boqun.feng@gmail.com>
---
v1 --> v2:
	* add a new write_cr4_safe()
	* use %pe for exception print
	* refactor the code based on Andrew's guide and advice
v2 --> v3:
	* add test_insns() to simplify test_main() logic
	* make write_cr4_safe() return 0 for success.
	* add UMIP activation test even if !cpu_has_umip

Test results:

* With UMIP patch:
** boot with hvm_fep: SUCCESS
** boot without hvm_fep: SKIP

* Without UMIP patch:
** boot with hvm_fep: SKIP
** boot without hvm_fep: SKIP

(illed implementation)
* With UMIP cpuid exposed but hvm_cr4_guest_valid_bits() didn't include X86_CR4_UMIP:
** boot with hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."
** boot without hvm_fep: FAILURE, due to "Fail: Unable to activate UMIP.."

* With UMIP cpuid not exposed but hvm_cr4_guest_valid_bits() included X86_CR4_UMIP:
** boot with hvm_fep: FAILURE, due to "UMIP unsupported, but setting CR4 succeeded"
** boot without hvm_fep: FAILURE, due to "UMIP unsupported, but setting CR4 succeeded"

 arch/x86/include/arch/lib.h |  13 +++
 docs/all-tests.dox          |   2 +
 tests/umip/Makefile         |   9 ++
 tests/umip/main.c           | 214 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+)
 create mode 100644 tests/umip/Makefile
 create mode 100644 tests/umip/main.c

diff --git a/arch/x86/include/arch/lib.h b/arch/x86/include/arch/lib.h
index f608af9996f0..82eb7da600c4 100644
--- a/arch/x86/include/arch/lib.h
+++ b/arch/x86/include/arch/lib.h
@@ -340,6 +340,19 @@ static inline void write_cr4(unsigned long cr4)
     asm volatile ("mov %0, %%cr4" :: "r" (cr4));
 }
 
+static inline bool write_cr4_safe(unsigned long cr4)
+{
+    exinfo_t fault = 0;
+
+    asm volatile ("1: mov %1, %%cr4; 2:"
+                  _ASM_EXTABLE_HANDLER(1b, 2b, ex_record_fault_edi)
+                  : "+D" (fault)
+                  : "r" (cr4),
+                    "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
 static inline void write_cr8(unsigned long cr8)
 {
     asm volatile ("mov %0, %%cr8" :: "r" (cr8));
diff --git a/docs/all-tests.dox b/docs/all-tests.dox
index c1b163a926cb..ef011007cf68 100644
--- a/docs/all-tests.dox
+++ b/docs/all-tests.dox
@@ -111,4 +111,6 @@ guest breakout.
 @section index-in-development In Development
 
 @subpage test-vvmx - Nested VT-x tests.
+
+@subpage test-umip - User-Mode Instruction Prevention
 */
diff --git a/tests/umip/Makefile b/tests/umip/Makefile
new file mode 100644
index 000000000000..0248c8b247a0
--- /dev/null
+++ b/tests/umip/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME      := umip
+CATEGORY  := functional
+TEST-ENVS := hvm32 hvm64
+
+obj-perenv += main.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/umip/main.c b/tests/umip/main.c
new file mode 100644
index 000000000000..76764c8b38f4
--- /dev/null
+++ b/tests/umip/main.c
@@ -0,0 +1,214 @@
+/**
+ * @file tests/umip/main.c
+ * @ref test-umip
+ *
+ * @page test-umip umip
+ *
+ * @todo Docs for test-umip
+ *
+ * @see tests/umip/main.c
+ */
+#include <xtf.h>
+#include <arch/exinfo.h>
+#include <arch/processor.h>
+
+const char test_title[] = "User-Mode Instruction Prevention Test";
+bool test_wants_user_mappings = true;
+
+static unsigned long stub_sgdt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    desc_ptr tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sgdt %[tmp]; 2:"
+                _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+		: "+D" (fault), [tmp] "=m" (tmp)
+                : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+static unsigned long stub_sidt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    desc_ptr tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sidt %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+		 : "+D" (fault), [tmp] "=m" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_sldt(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: sldt %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_str(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: str %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static unsigned long stub_smsw(unsigned long force)
+{
+    exinfo_t fault = 0;
+    unsigned int tmp;
+
+    asm volatile("test %[fep], %[fep];"
+                 "jz 1f;"
+                 _ASM_XEN_FEP
+                 "1: smsw %[tmp]; 2:"
+                 _ASM_EXTABLE_HANDLER(1b,2b, ex_record_fault_edi)
+                 : "+D" (fault), [tmp] "=r" (tmp)
+                 : [fep] "q" (force),
+                  "X" (ex_record_fault_edi));
+
+    return fault;
+}
+
+static const struct stub {
+    unsigned long (*fn)(unsigned long);
+    const char *name;
+} stubs[] = {
+    { stub_sgdt, "SGDT" },
+    { stub_sidt, "SIDT" },
+    { stub_sldt, "SLDT" },
+    { stub_str,  "STR" },
+    { stub_smsw, "SMSW" },
+};
+
+static void test_insns(bool umip_active, bool force)
+{
+    unsigned int i;
+    bool user;
+
+    for ( user = false; ; user = true )
+    {
+        exinfo_t exp = user && umip_active ? EXINFO_SYM(GP, 0) : 0;
+
+        for ( i = 0; i < ARRAY_SIZE(stubs); i++)
+        {
+            const struct stub *s = &stubs[i];
+            exinfo_t ret;
+
+            ret = user ? exec_user_param(s->fn, force) : s->fn(force);
+
+            /*
+             * Tolerate the instruction emulator not understanding these
+             * instructions in older releases of Xen.
+             */
+
+            if ( force && ret == EXINFO_SYM(UD, 0) )
+            {
+                static bool once;
+
+                if ( !once )
+                {
+                    xtf_skip("Skip: Emulator doesn't implement %s\n", s->name);
+                    once = true;
+                }
+
+                continue;
+            }
+
+            if ( ret != exp )
+                xtf_failure("Fail: %s %s\n"
+                            "  expected %pe\n"
+                            "       got %pe\n",
+                            user ? "user" : "supervisor", s->name,
+                            _p(exp), _p(ret));
+        }
+
+        if ( user )
+            break;
+    }
+}
+
+static void test_umip(bool umip_active)
+{
+    test_insns(umip_active, false);
+
+    if ( xtf_has_fep )
+        test_insns(umip_active, true);
+}
+
+void test_main(void)
+{
+    if ( !xtf_has_fep )
+        xtf_skip("FEP support not detected - some tests will be skipped\n");
+
+    test_umip(false);
+
+    if ( !cpu_has_umip )
+    {
+        xtf_skip("UMIP is not supported, skip the rest of test\n");
+
+        if ( !write_cr4_safe(read_cr4() | X86_CR4_UMIP) )
+            xtf_failure("UMIP unsupported, but setting CR4 bit succeeded\n");
+
+        return;
+    }
+
+    /* activate UMIP */
+    if ( write_cr4_safe(read_cr4() | X86_CR4_UMIP) )
+    {
+        xtf_failure("Fail: Unable to activate UMIP\n");
+        return;
+    }
+
+    test_umip(true);
+
+    /* deactivate UMIP */
+    if ( write_cr4_safe(read_cr4() & ~X86_CR4_UMIP) )
+    {
+        xtf_failure("Fail: Unable to deactivate UMIP\n");
+        return;
+    }
+
+    test_umip(false);
+
+    xtf_success(NULL);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.13.3


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

             reply	other threads:[~2017-08-15  3:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-15  3:18 Boqun Feng (Intel) [this message]
2017-08-15 10:28 ` [PATCH XTF v3] Functional: Add a UMIP test Andrew Cooper
2017-08-15 11:36   ` Yu Zhang

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=20170815031820.20234-1-boqun.feng@gmail.com \
    --to=boqun.feng@gmail.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=xen-devel@lists.xen.org \
    --cc=yu.c.zhang@linux.intel.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.