#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. */
/* 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
.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. */
GEN_SEQUENCE int_0x3
GEN_SEQUENCE icebp
GEN_SEQUENCE int_0x1
+#ifdef __i386__
+GEN_SEQUENCE into
+#endif
* - Ice Breakpoint (`0xf1`)
* - int_0x1
* - `int $1` (`0xcd 0x01`)
+ * - into
+ * - `into` (`0xce`)
*
* Prefixes `$Y`:
* - reg
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__ */
/*
* - `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
},
};
+#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;
{
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. */
{
idt[X86_EXC_DB].dpl = dpl;
idt[X86_EXC_BP].dpl = dpl;
+ idt[X86_EXC_OF].dpl = dpl;
}
/** Tests run in user mode. */
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");
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);
}
/* 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);
}
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");
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);
}