Add an extra entry to the selftests.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
#endif
}
+int xtf_set_idte(unsigned int vector, struct xtf_idte *idte)
+{
+#if defined(__i386__)
+ pack_gate32(&idt[vector], 14, idte->addr, idte->dpl, idte->cs);
+#elif defined(__x86_64__)
+ pack_gate64(&idt[vector], 14, idte->addr, idte->dpl, 0, idte->cs);
+#endif
+
+ return 0;
+}
+
void arch_init_traps(void)
{
setup_gate(X86_EXC_DE, &entry_DE, 0);
{ 0, 0, 0, 0 }, /* Sentinel. */
};
+int xtf_set_idte(unsigned int vector, struct xtf_idte *idte)
+{
+ struct xen_trap_info ti[2] =
+ {
+ { vector, idte->dpl | 4, idte->cs, idte->addr },
+ { 0, 0, 0, 0 }, /* Sentinel. */
+ };
+
+ return hypercall_set_trap_table(ti);
+}
+
#ifdef __i386__
static bool __used ex_pf_user(struct cpu_regs *regs,
const struct extable_entry *ex)
*/
#define X86_VEC_RET2KERN 0x20
+/**
+ * Available for test use.
+ */
+#define X86_VEC_AVAIL 0x21
+
+
+#ifndef __ASSEMBLY__
+
+/** A guest agnostic represention of IDT information. */
+struct xtf_idte
+{
+ unsigned long addr;
+ unsigned int cs, dpl;
+};
+
+/**
+ * Set up an IDT Entry, in a guest agnostic way.
+ *
+ * Construct an IDT Entry at the specified @p vector, using configuration
+ * provided in @p idte.
+ *
+ * @param vector Vector to set up.
+ * @param idte Details to set up.
+ * @returns 0 for HVM guests, hypercall result for PV guests.
+ */
+int xtf_set_idte(unsigned int vector,
+ struct xtf_idte *idte);
+
+#endif /* __ASSEMBLY__ */
+
#endif /* XTF_X86_IDT_H */
/*
*/
#include <xtf.h>
+#include <arch/x86/idt.h>
#include <arch/x86/processor.h>
#include <arch/x86/segment.h>
xtf_failure("Fail: Custom handler didn't run\n");
}
+void test_idte_handler(void);
+asm ("test_idte_handler:;"
+#if defined (CONFIG_PV) && defined (CONFIG_64BIT)
+ "pop %rcx; pop %r11;"
+#endif
+ "mov $0x1e51c0de, %eax;"
+#if defined (CONFIG_HVM)
+#ifdef __x86_64__
+ "rex64 "
+#endif
+ "iret;"
+#else /* CONFIG_HVM */
+#ifdef __x86_64__
+ "push $0;"
+#endif
+ "jmp HYPERCALL_iret;"
+#endif
+ );
+
+static void test_custom_idte(void)
+{
+ struct xtf_idte idte =
+ {
+ .addr = (unsigned long)test_idte_handler,
+ /* PV guests need DPL1, HVM need DPL0. */
+ .dpl = IS_DEFINED(CONFIG_PV) ? 1 : 0,
+ .cs = __KERN_CS,
+ };
+
+ printk("Test: Custom IDT entry\n");
+
+ int rc = xtf_set_idte(X86_VEC_AVAIL, &idte);
+
+ if ( rc )
+ return xtf_failure("Fail: xtf_set_idte() returned %d\n", rc);
+
+ unsigned int res;
+ asm volatile ("int $%c[vec]"
+ : "=a" (res)
+ : "0" (0),
+ [vec] "i" (X86_VEC_AVAIL));
+
+ if ( res != 0x1e51c0de )
+ xtf_failure("Fail: Unexpected result %#x\n", res);
+};
+
void test_main(void)
{
printk("XTF Selftests\n");
test_NULL_unmapped();
test_unhandled_exception_hook();
test_extable_handler();
+ test_custom_idte();
xtf_success(NULL);
}