]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
Test software injection of `into` in 32bit builds
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 14 Jan 2016 12:24:52 +0000 (12:24 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 14 Jan 2016 16:48:07 +0000 (16:48 +0000)
The `into` instruction is another software interrupt, which raises an #OF trap
if the overflow flag is set.  It is only recognised in 32bit code however, and
yields #UD if exectued in long mode.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
tests/swint-emulation/lowlevel.S
tests/swint-emulation/lowlevel.h
tests/swint-emulation/main.c

index 564f162c2524b5363f3ead0c088bfc4ca36283a2..a0856a6e8a62da1f0ba10805687f4b016487ad9d 100644 (file)
@@ -1,6 +1,7 @@
 #include <xtf/extable.h>
 #include <xtf/asm_macros.h>
 #include <xen/arch-x86/xen.h>
+#include <arch/x86/processor.h>
 
         /* Macro to generate a single test function. */
         /* See lowlevel.h for a description of nomenclature. */
@@ -9,8 +10,15 @@
         /* Function label.  e.g. stub_int3_red(). */
 ENTRY(stub_\insn\()_\type)
 
-        /* Avoid function label and fault label possibly aliasing. */
-        nop
+        .if \insn == into
+            /* Ensure the overflow flag is set, to trigger 'into'. */
+            pushf
+            orl $X86_EFLAGS_OF, (%esp)
+            popf
+        .else
+            /* Avoid function label and fault label possibly aliasing. */
+            nop
+        .endif
 
         /* Possibly insert a Xen Forced Emulation prefix. */
         .if \type == force || \type == forcered
@@ -39,6 +47,8 @@ GLOBAL(label_\insn\()_\type\()_fault)
             .byte 0xf1
         .elseif \insn == int_0x1
             int $0x1
+        .elseif \insn == into
+            into
         .endif
 
         /* Label where a trap should occur.  e.g. label_int3_red_trap. */
@@ -65,3 +75,6 @@ GEN_SEQUENCE int3
 GEN_SEQUENCE int_0x3
 GEN_SEQUENCE icebp
 GEN_SEQUENCE int_0x1
+#ifdef __i386__
+GEN_SEQUENCE into
+#endif
index 94ed1e4d3d0ca2fd668d8f7d0cd115af1a250ee3..f4eaa2bf6b57569d574d2fc550962b7ded7900a2 100644 (file)
@@ -18,6 +18,8 @@
  *   - Ice Breakpoint (`0xf1`)
  * - int_0x1
  *   - `int $1` (`0xcd 0x01`)
+ * - into
+ *   - `into` (`0xce`)
  *
  * Prefixes `$Y`:
  * - reg
@@ -68,6 +70,17 @@ extern unsigned long label_int_0x1_red_trap[], label_int_0x1_red_fault[];
 extern unsigned long label_int_0x1_force_trap[], label_int_0x1_force_fault[];
 extern unsigned long label_int_0x1_forcered_trap[], label_int_0x1_forcered_fault[];
 
+#ifdef __i386__
+void stub_into_reg(void);
+void stub_into_red(void);
+void stub_into_force(void);
+void stub_into_forcered(void);
+extern unsigned long label_into_reg_trap[], label_into_reg_fault[];
+extern unsigned long label_into_red_trap[], label_into_red_fault[];
+extern unsigned long label_into_force_trap[], label_into_force_fault[];
+extern unsigned long label_into_forcered_trap[], label_into_forcered_fault[];
+#endif
+
 #endif /* __LOWLEVEL_H__ */
 
 /*
index 1156f546899b2409d1a514b58a8a6d4820911c59..145530a8b4dc96e5d0bc1603f487dfa51f5527b4 100644 (file)
@@ -15,6 +15,7 @@
  * - `int $3` (`0xcd 0x03`)
  * - `icebp`  (`0xf1`)
  * - `int $1` (`0xcd 0x01`)
+ * - `into`   (`0xce`) (32bit only)
  *
  * with and without a redundant prefix (address size override specifically, as
  * it has no effect on instructs like these).  Each combination is executed
@@ -131,6 +132,26 @@ struct sequence int_0x1 =
   },
 };
 
+#ifdef __i386__
+/** Sequence for `into`. */
+struct sequence into =
+{ "into",
+  {
+      {"regular", stub_into_reg,
+       label_into_reg_trap, label_into_reg_fault},
+
+      {"redundant", stub_into_red,
+       label_into_red_trap, label_into_red_fault},
+
+      {"forced", stub_into_force,
+       label_into_force_trap, label_into_force_fault},
+
+      {"forced redundant", stub_into_forcered,
+       label_into_forcered_trap, label_into_forcered_fault},
+  },
+};
+#endif
+
 /** Whether to run the stub in user or supervisor mode. */
 static bool user = false;
 
@@ -237,6 +258,7 @@ static void set_idt_entries_present(bool present)
 {
     idt[X86_EXC_DB].p = present;
     idt[X86_EXC_BP].p = present;
+    idt[X86_EXC_OF].p = present;
 }
 
 /** Modify the descriptor privilege level on the IDT entries under test. */
@@ -244,6 +266,7 @@ static void set_idt_entries_dpl(unsigned int dpl)
 {
     idt[X86_EXC_DB].dpl = dpl;
     idt[X86_EXC_BP].dpl = dpl;
+    idt[X86_EXC_OF].dpl = dpl;
 }
 
 /** Tests run in user mode. */
@@ -257,6 +280,9 @@ void cpl3_tests(void)
         test_trap(&int_0x3, X86_EXC_BP);
         test_trap(&icebp,   X86_EXC_DB);
         test_trap(&int_0x1, X86_EXC_DB);
+#ifdef __i386__
+        test_trap(&into,    X86_EXC_OF);
+#endif
     }
 
     printk("Test cpl3: p=0\n");
@@ -267,6 +293,9 @@ void cpl3_tests(void)
         test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP));
         test_fault(&icebp,   X86_EXC_NP, EXC_EC_SYM(DB, EXT));
         test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB));
+#ifdef __i386__
+        test_fault(&into,    X86_EXC_NP, EXC_EC_SYM(OF));
+#endif
 
         set_idt_entries_present(true);
     }
@@ -280,6 +309,9 @@ void cpl3_tests(void)
          /* icebp count as external, so no dpl check. */
         test_trap (&icebp,   X86_EXC_DB);
         test_fault(&int_0x1, X86_EXC_GP, EXC_EC_SYM(DB));
+#ifdef __i386__
+        test_fault(&into,    X86_EXC_GP, EXC_EC_SYM(OF));
+#endif
 
         set_idt_entries_dpl(3);
     }
@@ -296,6 +328,9 @@ void cpl0_tests(void)
         test_trap(&int_0x3, X86_EXC_BP);
         test_trap(&icebp,   X86_EXC_DB);
         test_trap(&int_0x1, X86_EXC_DB);
+#ifdef __i386__
+        test_trap(&into,    X86_EXC_OF);
+#endif
     }
 
     printk("Test cpl0: p=0\n");
@@ -306,6 +341,9 @@ void cpl0_tests(void)
         test_fault(&int_0x3, X86_EXC_NP, EXC_EC_SYM(BP));
         test_fault(&icebp,   X86_EXC_NP, EXC_EC_SYM(DB, EXT));
         test_fault(&int_0x1, X86_EXC_NP, EXC_EC_SYM(DB));
+#ifdef __i386__
+        test_fault(&into,    X86_EXC_NP, EXC_EC_SYM(OF));
+#endif
 
         set_idt_entries_present(true);
     }