]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
test-swint: Update to use ex_record rather than exlog
authorAndrew Cooper <andrew.cooper3@citrix.com>
Sat, 2 Mar 2024 21:14:54 +0000 (21:14 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Sun, 3 Mar 2024 00:13:29 +0000 (00:13 +0000)
This is both more precise and consice.

As this test pertains to mixing up faults and traps, introduce EXINFO_TRAP and
ex_record_trap_eax() to distinguish which EXTABLE entry was used.  This in
turn means we don't need to export the trap/fault labels to C.

Change the nomeclature for instruction prefixes, because "red" is fairly
meaningless and confusing in context.

No change in test behaviour.

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 b7bf0fc76dc410cb30f3e732a61a2882f230c00f..53bb72cd4201f5234cf2f1b971b56d05cdf70a6e 100644 (file)
@@ -5,30 +5,24 @@
 
         /* Macro to generate a single test function. */
         /* See lowlevel.h for a description of nomenclature. */
-.macro GEN_SINGLE insn, type
+.macro GEN_SINGLE name, insn, fep=0, addr=0
 
-        /* Function label.  e.g. stub_int3_red(). */
-ENTRY(stub_\insn\()_\type)
+ENTRY(stub_\name)
+
+       xor %eax, %eax
 
         .ifc \insn, into
             /* Ensure the overflow flag is set, to trigger 'into'. */
-            mov $0x7f, %al
-            add %al, %al
-        .else
-            /* Avoid function label and fault label possibly aliasing. */
-            nop
+            mov $0x7f, %dl
+            add %dl, %dl
         .endif
 
         /* Possibly insert a Xen Forced Emulation prefix. */
-        .ifc \type, force
-            _ASM_XEN_FEP
-        .endif
-        .ifc \type, forcered
+        .if \fep
             _ASM_XEN_FEP
         .endif
 
-        /* Label where a fault should occur.  e.g. label_int3_red_fault. */
-GLOBAL(label_\insn\()_\type\()_fault)
+.L_\name\()_fault:
 
         /*
          * Possibly insert a redundant prefix.
@@ -36,10 +30,7 @@ GLOBAL(label_\insn\()_\type\()_fault)
          * Uses 'address size override' which has no effect on any of the
          * target instructions, but in a form which GAS won't complain about.
          */
-        .ifc \type, red
-            .byte 0x67
-        .endif
-        .ifc \type, forcered
+        .if \addr
             .byte 0x67
         .endif
 
@@ -60,27 +51,22 @@ GLOBAL(label_\insn\()_\type\()_fault)
             .byte 0xce           /* Raw opcode to avoid failure in 64bit build. */
         .endif
 
-        /* Label where a trap should occur.  e.g. label_int3_red_trap. */
-GLOBAL(label_\insn\()_\type\()_trap)
+.L_\name\()_trap:
 
-        /* Function return. */
         ret
 
-        /* Fixup from fault label to trap label. */
-        _ASM_EXTABLE(label_\insn\()_\type\()_fault,
-                     label_\insn\()_\type\()_trap)
-        /* Mark traps as ok. */
-        _ASM_TRAP_OK(label_\insn\()_\type\()_trap)
+       _ASM_EXTABLE_HANDLER(.L_\name\()_fault, .L_\name\()_trap, ex_record_fault_eax)
+       _ASM_EXTABLE_HANDLER(.L_\name\()_trap,  .L_\name\()_trap, ex_record_trap_eax)
 
-ENDFUNC(stub_\insn\()_\type)
+ENDFUNC(stub_\name\())
 .endm
 
         /* For a single instruction, generate each test variant. */
 .macro GEN_SEQUENCE insn
-        GEN_SINGLE \insn reg
-        GEN_SINGLE \insn red
-        GEN_SINGLE \insn force
-        GEN_SINGLE \insn forcered
+        GEN_SINGLE \insn       \insn
+        GEN_SINGLE \insn\()_A  \insn addr=1
+        GEN_SINGLE \insn\()_F  \insn fep=1
+        GEN_SINGLE \insn\()_FA \insn fep=1 addr=1
 .endm
 
         /* Generate test sequences for each instruction. */
index 1cbe8cb71a1204765383c5b65fb9e4090fe0d022..e3ab75506adbcf990b7ad890dd820ac278135a97 100644 (file)
@@ -6,8 +6,6 @@
  * Nomaclature:
  * - `stub_$X_$Y()`
  *   - Stub function executing instruction `$X` with prefix `$Y`.
- * - `label_$X_$Y_{trap, fault}:`
- *   - Labels for where `$X` is expected to trap or fault.
  *
  * Instructions `$X`:
  * - int3
  *   - `into` (`0xce`)
  *
  * Prefixes `$Y`:
- * - reg
+ * - (none)
  *   - Regular - no prefix
- * - red
- *   - Redundant - address size override prefix (`0x67`)
- * - force
+ * - A
+ *   - Address size override prefix (`0x67`)
+ * - F
  *   - Forced Emulation prefix - see @ref _ASM_XEN_FEP
- * - forcered
- *   - Forced Emulation and redundant prefixes
+ * - FA
+ *   - Forced Emulation and Address override prefixes
  */
 #ifndef __LOWLEVEL_H__
 #define __LOWLEVEL_H__
 
-void stub_int3_reg(void);
-void stub_int3_red(void);
-void stub_int3_force(void);
-void stub_int3_forcered(void);
-extern unsigned long label_int3_reg_trap[], label_int3_reg_fault[];
-extern unsigned long label_int3_red_trap[], label_int3_red_fault[];
-extern unsigned long label_int3_force_trap[], label_int3_force_fault[];
-extern unsigned long label_int3_forcered_trap[], label_int3_forcered_fault[];
+unsigned long stub_int3(void);
+unsigned long stub_int3_A(void);
+unsigned long stub_int3_F(void);
+unsigned long stub_int3_FA(void);
 
-void stub_int_0x3_reg(void);
-void stub_int_0x3_red(void);
-void stub_int_0x3_force(void);
-void stub_int_0x3_forcered(void);
-extern unsigned long label_int_0x3_reg_trap[], label_int_0x3_reg_fault[];
-extern unsigned long label_int_0x3_red_trap[], label_int_0x3_red_fault[];
-extern unsigned long label_int_0x3_force_trap[], label_int_0x3_force_fault[];
-extern unsigned long label_int_0x3_forcered_trap[], label_int_0x3_forcered_fault[];
+unsigned long stub_int_0x3(void);
+unsigned long stub_int_0x3_A(void);
+unsigned long stub_int_0x3_F(void);
+unsigned long stub_int_0x3_FA(void);
 
-void stub_icebp_reg(void);
-void stub_icebp_red(void);
-void stub_icebp_force(void);
-void stub_icebp_forcered(void);
-extern unsigned long label_icebp_reg_trap[], label_icebp_reg_fault[];
-extern unsigned long label_icebp_red_trap[], label_icebp_red_fault[];
-extern unsigned long label_icebp_force_trap[], label_icebp_force_fault[];
-extern unsigned long label_icebp_forcered_trap[], label_icebp_forcered_fault[];
+unsigned long stub_icebp(void);
+unsigned long stub_icebp_A(void);
+unsigned long stub_icebp_F(void);
+unsigned long stub_icebp_FA(void);
 
-void stub_int_0x1_reg(void);
-void stub_int_0x1_red(void);
-void stub_int_0x1_force(void);
-void stub_int_0x1_forcered(void);
-extern unsigned long label_int_0x1_reg_trap[], label_int_0x1_reg_fault[];
-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[];
+unsigned long stub_int_0x1(void);
+unsigned long stub_int_0x1_A(void);
+unsigned long stub_int_0x1_F(void);
+unsigned long stub_int_0x1_FA(void);
 
-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[];
+unsigned long stub_into(void);
+unsigned long stub_into_A(void);
+unsigned long stub_into_F(void);
+unsigned long stub_into_FA(void);
 
 #endif /* __LOWLEVEL_H__ */
 
index 92ca98be3a6df418a70409e0a1a2f51386b3008a..a4d1452e688f4eedc75b44a8d411e3cad885e1ac 100644 (file)
@@ -58,188 +58,92 @@ bool test_wants_user_mappings = true;
 # define COND(_32, _64) _64
 #endif
 
+#define EXINFO_TRAP EXINFO_AVAIL0
+
 enum mode { KERN, USER };
 
-/** Single stub's worth of information. */
-struct single
+bool ex_record_trap_eax(struct cpu_regs *regs, const struct extable_entry *ex)
 {
-    const char *type;
-    void (*fn)(void);
-    void *trap, *fault;
-};
+    regs->ax = EXINFO(regs->entry_vector, regs->error_code) | EXINFO_TRAP;
+    regs->ip = ex->fixup;
+
+    return true;
+}
 
 struct insn
 {
     const char *name;
-    struct single tests[4];
+    unsigned long (*fn[4])(void);
 };
 
 const struct insn int3 = {
     "int3",
     {
-      {"regular", stub_int3_reg,
-       label_int3_reg_trap, label_int3_reg_fault},
-
-      {"redundant", stub_int3_red,
-       label_int3_red_trap, label_int3_red_fault},
-
-      {"forced", stub_int3_force,
-       label_int3_force_trap, label_int3_force_fault},
-
-      {"forced redundant", stub_int3_forcered,
-       label_int3_forcered_trap, label_int3_forcered_fault},
+        stub_int3,
+        stub_int3_A,
+        stub_int3_F,
+        stub_int3_FA,
     },
 };
 
 const struct insn int_0x3 = {
     "int $3",
     {
-      {"regular", stub_int_0x3_reg,
-       label_int_0x3_reg_trap, label_int_0x3_reg_fault},
-
-      {"redundant", stub_int_0x3_red,
-       label_int_0x3_red_trap, label_int_0x3_red_fault},
-
-      {"forced", stub_int_0x3_force,
-       label_int_0x3_force_trap, label_int_0x3_force_fault},
-
-      {"forced redundant", stub_int_0x3_forcered,
-       label_int_0x3_forcered_trap, label_int_0x3_forcered_fault},
+        stub_int_0x3,
+        stub_int_0x3_A,
+        stub_int_0x3_F,
+        stub_int_0x3_FA,
     },
 };
 
 const struct insn icebp = {
     "icebp",
     {
-      {"regular", stub_icebp_reg,
-       label_icebp_reg_trap, label_icebp_reg_fault},
-
-      {"redundant", stub_icebp_red,
-       label_icebp_red_trap, label_icebp_red_fault},
-
-      {"forced", stub_icebp_force,
-       label_icebp_force_trap, label_icebp_force_fault},
-
-      {"forced redundant", stub_icebp_forcered,
-       label_icebp_forcered_trap, label_icebp_forcered_fault},
+        stub_icebp,
+        stub_icebp_A,
+        stub_icebp_F,
+        stub_icebp_FA,
     },
 };
 
 const struct insn int_0x1 = {
     "int $1",
     {
-      {"regular", stub_int_0x1_reg,
-       label_int_0x1_reg_trap, label_int_0x1_reg_fault},
-
-      {"redundant", stub_int_0x1_red,
-       label_int_0x1_red_trap, label_int_0x1_red_fault},
-
-      {"forced", stub_int_0x1_force,
-       label_int_0x1_force_trap, label_int_0x1_force_fault},
-
-      {"forced redundant", stub_int_0x1_forcered,
-       label_int_0x1_forcered_trap, label_int_0x1_forcered_fault},
+        stub_int_0x1,
+        stub_int_0x1_A,
+        stub_int_0x1_F,
+        stub_int_0x1_FA,
     },
 };
 
 const struct insn 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},
+        stub_into,
+        stub_into_A,
+        stub_into_F,
+        stub_into_FA,
     },
 };
 
-struct expectation {
-    const char *prefix;
-    const void *ip;
-    unsigned int ev, ec;
-} /** Expected %%eip, vector and error code from the stub under test. */
-    expectation;
-
-/** Latch details of the stub under test. */
-void expect(const void *prefix, const void *ip,
-            unsigned int ev, unsigned int ec)
-{
-    expectation = (struct expectation){prefix, ip, ev, ec};
-    xtf_exlog_reset();
-}
-
-/** Check the exception long against the expected details. */
-void check(void)
-{
-    unsigned int entries = xtf_exlog_entries();
-
-    if ( entries != 1 )
-    {
-        xtf_failure("Fail %s: Expected 1 exception (vec %u at %p), got %u\n",
-                    expectation.prefix, expectation.ev,
-                    expectation.ip, entries);
-        xtf_exlog_dump_log();
-        return;
-    }
-
-    exlog_entry_t *entry = xtf_exlog_entry(0);
-    if ( !entry )
-    {
-        xtf_failure("Fail %s: Unable to retrieve exception log\n",
-                    expectation.prefix);
-        return;
-    }
-
-    if ( (_p(entry->ip) != expectation.ip) ||
-         (entry->ev != expectation.ev) ||
-         (entry->ec != expectation.ec) )
-    {
-        xtf_failure("Fail %s:\n"
-                    "  Expected vec %2u[%04x] at %p\n"
-                    "       got vec %2u[%04x] at %p\n",
-                    expectation.prefix,
-                    expectation.ev, expectation.ec, expectation.ip,
-                    entry->ev, entry->ec, _p(entry->ip));
-        return;
-    }
-}
-
-/** Print expected information in the case of an unexpected exception. */
-bool do_unhandled_exception(struct cpu_regs *regs)
-{
-    printk("Unhandled Exception at %p\n", _p(regs));
-    check();
-
-    return false;
-}
-
 void test_insn(enum mode user, const struct insn *insn, exinfo_t exp)
 {
-    unsigned int vector = exinfo_vec(exp);
-    unsigned int error = exinfo_ec(exp);
-    bool fault = X86_EXC_FAULTS & (1u << vector);
-
     printk("  Testing %s\n", insn->name);
 
-    for ( unsigned int i = 0; i < ARRAY_SIZE(insn->tests); ++i )
+    for ( unsigned int i = 0; i < ARRAY_SIZE(insn->fn); ++i )
     {
-        const struct single *s = &insn->tests[i];
-
-        expect(s->type,
-               fault ? s->fault : s->trap,
-               vector, error);
+        exinfo_t got;
 
-        user ? exec_user_void(s->fn) : s->fn();
+        got = user ? exec_user(insn->fn[i]) : insn->fn[i]();
 
-        check();
+        if ( exp != got )
+            xtf_failure("    Fail (Force%c, Addr%c): expected %pe %s, got %pe %s\n",
+                        i & 1 ? '+' : '-',
+                        i & 2 ? '+' : '-',
+                        _p(exp), exp & EXINFO_TRAP ? "trap" : "fault",
+                        _p(got), got & EXINFO_TRAP ? "trap" : "fault");
 
-        /* Avoid 'force' and 'forcered' stubs if FEP isn't available. */
+        /* Avoid FEP stubs if FEP isn't available. */
         if ( i == 1 && !xtf_has_fep )
             break;
     }
@@ -261,7 +165,7 @@ static void set_idt_entries_dpl(unsigned int dpl)
     idt[X86_EXC_OF].dpl = dpl;
 }
 
-#define TRAP(V)          EXINFO_SYM(V, 0)
+#define TRAP(V)          EXINFO_SYM(V, 0) | EXINFO_TRAP
 #define FAULT(V)         EXINFO_SYM(V, 0)
 #define FAULT_EC(V, ...) EXINFO_SYM(V, EXC_EC_SYM(__VA_ARGS__))
 
@@ -342,13 +246,9 @@ void test_main(void)
     set_idt_entries_present(true);
     set_idt_entries_dpl(3);
 
-    xtf_exlog_start();
-
     cpl0_tests();
     cpl3_tests();
 
-    xtf_exlog_stop();
-
     xtf_success(NULL);
 }