]> xenbits.xensource.com Git - xtf.git/commitdiff
Introduce exinfo_t to formalise the existing ad-hoc exception encapsulation
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 3 Oct 2016 13:12:00 +0000 (13:12 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 27 Oct 2016 13:12:28 +0000 (14:12 +0100)
Set the top bit to distinguish a DivideError from no exception.  Add
x86_decode_exinfo() to assist printing an exinfo_t.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/decode.c
arch/x86/extable.c
include/arch/x86/decode.h
include/arch/x86/exinfo.h [new file with mode: 0644]
tests/cpuid-faulting/main.c
tests/fpu-exception-emulation/main.c

index 0922036ae385fab87ee4620bdb770bc6c31a3148..b654b1dd2b816e9b0848a23c42b85fc663637fc6 100644 (file)
@@ -68,6 +68,25 @@ int x86_exc_decode_ec(char *buf, size_t bufsz, unsigned int ev, unsigned int ec)
     }
 }
 
+int x86_decode_exinfo(char *buf, size_t bufsz, exinfo_t info)
+{
+    if ( !info )
+        return snprintf(buf, bufsz, "nothing");
+
+    unsigned int vec = exinfo_vec(info), ec = exinfo_ec(info);
+
+    if ( ec || ((vec < 32) && ((1u << vec) & X86_EXC_HAVE_EC)) )
+    {
+        char ecstr[16];
+
+        x86_exc_decode_ec(ecstr, ARRAY_SIZE(ecstr), vec, ec);
+
+        return snprintf(buf, bufsz, "%s[%s]", x86_exc_short_name(vec), ecstr);
+    }
+    else
+        return snprintf(buf, bufsz, "%s", x86_exc_short_name(vec));
+}
+
 /*
  * Local variables:
  * mode: C
index 39230146c438103cff45325150ba6f2b9dba5ef6..5099d2b465e4b30bb7096e46aa5f2cd2875e04c4 100644 (file)
@@ -6,6 +6,7 @@
 #include <xtf/lib.h>
 #include <xtf/extable.h>
 
+#include <arch/x86/exinfo.h>
 #include <arch/x86/regs.h>
 
 /**
@@ -20,7 +21,7 @@
  */
 bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
 {
-    regs->ax = (uint32_t)(regs->entry_vector << 16) | regs->error_code;
+    regs->ax = EXINFO(regs->entry_vector, regs->error_code);
     regs->ip = ex->fixup;
 
     return true;
@@ -38,7 +39,7 @@ bool ex_record_fault_eax(struct cpu_regs *regs, const struct extable_entry *ex)
  */
 bool ex_record_fault_edi(struct cpu_regs *regs, const struct extable_entry *ex)
 {
-    regs->di = (uint32_t)(regs->entry_vector << 16) | regs->error_code;
+    regs->di = EXINFO(regs->entry_vector, regs->error_code);
     regs->ip = ex->fixup;
 
     return true;
index 930af1e65aa56a81bd830153b6661c821d549f21..0bd650359e907b79d9392bd87b57b1094c78335f 100644 (file)
@@ -9,6 +9,7 @@
 #include <xtf/types.h>
 
 #include <arch/x86/cpuid.h>
+#include <arch/x86/exinfo.h>
 
 /**
  * String of the indentified vendor @p v.
@@ -38,6 +39,16 @@ const char *x86_exc_short_name(unsigned int ev);
 int x86_exc_decode_ec(char *buf, size_t bufsz,
                       unsigned int ev, unsigned int ec);
 
+/**
+ * Decodes an exinfo_t into a readable form.
+ *
+ * @param buf Buffer to fill.
+ * @param bufsz Size of @p buf.
+ * @param info exinfo_t value.
+ * @return snprintf(buf, bufsz, ...)
+ */
+int x86_decode_exinfo(char *buf, size_t bufsz, exinfo_t info);
+
 #endif /* XTF_X86_DECODE_H */
 
 /*
diff --git a/include/arch/x86/exinfo.h b/include/arch/x86/exinfo.h
new file mode 100644 (file)
index 0000000..eef39b6
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * @file include/arch/x86/exinfo.h
+ *
+ * An encapsulation of an x86 exception with error code
+ */
+#ifndef XTF_X86_EXINFO_H
+#define XTF_X86_EXINFO_H
+
+#include <arch/x86/processor.h>
+
+/**
+ * Packed exception and error code information
+ *
+ * - Bottom 16 bits are error code
+ * - Next 8 bits are the entry vector
+ * - Top bit it set to disambiguate @#DE from no exception
+ */
+typedef unsigned int exinfo_t;
+
+#define EXINFO_EXPECTED (1u << 31)
+
+#define EXINFO(vec, ec) (EXINFO_EXPECTED | ((vec & 0xff) << 16) | (ec & 0xffff))
+
+#define EXINFO_SYM(exc, ec) EXINFO(X86_EXC_ ## exc, ec)
+
+static inline unsigned int exinfo_vec(exinfo_t info)
+{
+    return (info >> 16) & 0xff;
+}
+
+static inline unsigned int exinfo_ec(exinfo_t info)
+{
+    return info & 0xffff;
+}
+
+#endif /* XTF_X86_EXINFO_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index e30ff8732b5c4cb8651f6dd8c7552d4a60ad1da1..be0d40a9d3a8dede0003fe14fa5d31be2b55b5ef 100644 (file)
  */
 #include <xtf.h>
 
+#include <arch/x86/exinfo.h>
 #include <arch/x86/msr-index.h>
 #include <arch/x86/processor.h>
 
 bool test_wants_user_mappings = true;
 
-#define EXC_SYM(vec, ec) ((X86_EXC_ ## vec) << 16 | ec)
-
 unsigned long stub_cpuid(void)
 {
     unsigned int fault = 0, tmp;
@@ -72,7 +71,7 @@ static void test_cpuid(bool exp_faulting)
     /*
      * User cpuids should raise #GP[0] if faulting is enabled.
      */
-    unsigned long exp = exp_faulting ? EXC_SYM(GP, 0) : 0;
+    unsigned long exp = exp_faulting ? EXINFO_SYM(GP, 0) : 0;
     const char *exp_fail_str = exp_faulting ? "didn't fault" : "faulted";
 
     if ( exec_user(stub_cpuid) != exp )
index ea4d4690e196bbf986caded5f7adc87eb49f1908..a2d37a25b864225eeda5e57e0d500d6ad0e4341f 100644 (file)
 #include <xtf.h>
 
 #include <arch/x86/decode.h>
+#include <arch/x86/exinfo.h>
 #include <arch/x86/processor.h>
 #include <arch/x86/symbolic-const.h>
 
 #define CR0_SYM(...) TOK_OR(X86_CR0_, ##__VA_ARGS__)
 #define CR0_MASK CR0_SYM(EM, MP, TS)
 
-#define EXC_SYM(vec, ec) ((X86_EXC_ ## vec) << 16 | ec)
-
 struct test_cfg
 {
     unsigned long cr0;
-    unsigned long fault;
+    exinfo_t fault;
 };
 
 static unsigned long zero;
@@ -61,18 +60,18 @@ static unsigned long default_cr0;
 static const struct test_cfg x87[] =
 {
     { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), EXC_SYM(NM, 0) },
+    { CR0_SYM(        TS), EXINFO_SYM(NM, 0) },
     { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXC_SYM(NM, 0) },
-    { CR0_SYM(EM        ), EXC_SYM(NM, 0) },
-    { CR0_SYM(EM,     TS), EXC_SYM(NM, 0) },
-    { CR0_SYM(EM, MP    ), EXC_SYM(NM, 0) },
-    { CR0_SYM(EM, MP, TS), EXC_SYM(NM, 0) },
+    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM,     TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM, MP    ), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
 };
 
-unsigned int probe_x87(bool force)
+exinfo_t probe_x87(bool force)
 {
-    unsigned int fault = 0;
+    exinfo_t fault = 0;
 
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
@@ -96,16 +95,16 @@ static const struct test_cfg x87_wait[] =
     { CR0_SYM(          ), 0 },
     { CR0_SYM(        TS), 0 },
     { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXC_SYM(NM, 0) },
+    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
     { CR0_SYM(EM        ), 0 },
     { CR0_SYM(EM,     TS), 0 },
     { CR0_SYM(EM, MP    ), 0 },
-    { CR0_SYM(EM, MP, TS), EXC_SYM(NM, 0) },
+    { CR0_SYM(EM, MP, TS), EXINFO_SYM(NM, 0) },
 };
 
-unsigned int probe_x87_wait(bool force)
+exinfo_t probe_x87_wait(bool force)
 {
-    unsigned int fault = 0;
+    exinfo_t fault = 0;
 
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
@@ -125,18 +124,18 @@ unsigned int probe_x87_wait(bool force)
 static const struct test_cfg mmx_sse[] =
 {
     { CR0_SYM(          ), 0 },
-    { CR0_SYM(        TS), EXC_SYM(NM, 0) },
+    { CR0_SYM(        TS), EXINFO_SYM(NM, 0) },
     { CR0_SYM(    MP    ), 0 },
-    { CR0_SYM(    MP, TS), EXC_SYM(NM, 0) },
-    { CR0_SYM(EM        ), EXC_SYM(UD, 0) },
-    { CR0_SYM(EM,     TS), EXC_SYM(UD, 0) },
-    { CR0_SYM(EM, MP    ), EXC_SYM(UD, 0) },
-    { CR0_SYM(EM, MP, TS), EXC_SYM(UD, 0) },
+    { CR0_SYM(    MP, TS), EXINFO_SYM(NM, 0) },
+    { CR0_SYM(EM        ), EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM,     TS), EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP    ), EXINFO_SYM(UD, 0) },
+    { CR0_SYM(EM, MP, TS), EXINFO_SYM(UD, 0) },
 };
 
-unsigned int probe_mmx(bool force)
+exinfo_t probe_mmx(bool force)
 {
-    unsigned int fault = 0;
+    exinfo_t fault = 0;
 
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
@@ -150,9 +149,9 @@ unsigned int probe_mmx(bool force)
     return fault;
 }
 
-unsigned int probe_sse(bool force)
+exinfo_t probe_sse(bool force)
 {
-    unsigned int fault = 0;
+    exinfo_t fault = 0;
 
     asm volatile ("test %[fep], %[fep];"
                   "jz 1f;"
@@ -167,31 +166,32 @@ unsigned int probe_sse(bool force)
 }
 
 void run_sequence(const struct test_cfg *seq, unsigned int nr,
-                  unsigned int (*fn)(bool), bool force, unsigned int override)
+                  unsigned int (*fn)(bool), bool force, exinfo_t override)
 {
     unsigned int i;
 
     for ( i = 0; i < nr; ++i )
     {
         const struct test_cfg *t = &seq[i];
-        unsigned int res, exp = override ?: t->fault;
+        exinfo_t res, exp = override ?: t->fault;
 
         write_cr0((default_cr0 & ~CR0_MASK) | t->cr0);
         res = fn(force);
 
         if ( res != exp )
         {
-            char buf[24];
+            char expstr[12], gotstr[12], cr0str[12];
+
+            x86_decode_exinfo(expstr, ARRAY_SIZE(expstr), exp);
+            x86_decode_exinfo(gotstr, ARRAY_SIZE(gotstr), res);
 
-            snprintf(buf, sizeof(buf), "%s%s%s",
+            snprintf(cr0str, sizeof(cr0str), "%s%s%s",
                      t->cr0 & X86_CR0_EM ? " EM" : "",
                      t->cr0 & X86_CR0_MP ? " MP" : "",
                      t->cr0 & X86_CR0_TS ? " TS" : "");
 
             xtf_failure("  Expected %s, got %s (cr0:%s)\n",
-                        exp ? x86_exc_short_name(exp >> 16) : "none",
-                        res ? x86_exc_short_name(res >> 16) : "none",
-                        buf[0] ? buf : " - ");
+                        expstr, gotstr, cr0str[0] ? cr0str : " - ");
         }
     }
 }
@@ -219,7 +219,8 @@ void run_tests(bool force)
 
         printk("Testing%s SSE\n", force ? " emulated" : "");
         write_cr4(cr4 & ~X86_CR4_OSFXSR);
-        run_sequence(mmx_sse, ARRAY_SIZE(mmx_sse), probe_sse, force, EXC_SYM(UD, 0));
+        run_sequence(mmx_sse, ARRAY_SIZE(mmx_sse), probe_sse, force,
+                     EXINFO_SYM(UD, 0));
 
         printk("Testing%s SSE (CR4.OSFXSR)\n", force ? " emulated" : "");
         write_cr4(cr4 | X86_CR4_OSFXSR);