Current changes introduce common x86 traps definitions and functions for both
Xen and KVM platforms. Trap names are enforced by the helper macros which
should be used when defining a new trap function. Whenever a platform needs to
add new traps it should define the trap number in
'plat/name/include/arch/traps.h' and the C trap handler in
'plat/name/arch/traps.c'. The assembly stub name should also follow the
convention specified in 'plat/common/include/x86/traps.h'.
The Xen specific traps work as an example for this rule.
Other changes:
* HVM traps updates for conforming with the new traps and segment descriptors
definitions
* 'os.h' cleanup; the goal is to get rid of this header
* minor change in 'plat/xen/x86/arch_time.c'
Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
---
plat/common/include/x86/traps.h | 115 +++++++++++++++++
plat/common/x86/traps.c | 116 +++++++++++++++++
plat/xen/Makefile.uk | 1 +
plat/xen/include/xen-x86/os.h | 34 -----
plat/xen/include/xen-x86/traps.h | 23 ++--
plat/xen/x86/arch_time.c | 2 +-
plat/xen/x86/entry64.S | 108 ++++++----------
plat/xen/x86/setup.c | 2 +-
plat/xen/x86/traps.c | 263 +++++++++------------------------------
9 files changed, 340 insertions(+), 324 deletions(-)
create mode 100644 plat/common/include/x86/traps.h
create mode 100644 plat/common/x86/traps.c
diff --git a/plat/common/include/x86/traps.h b/plat/common/include/x86/traps.h
new file mode 100644
index 0000000..b217b34
--- /dev/null
+++ b/plat/common/include/x86/traps.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+/* Ported from Mini-OS */
+
+#ifndef __UKARCH_TRAPS_X86_64_H__
+#define __UKARCH_TRAPS_X86_64_H__
+
+#include <x86/regs.h>
+
+#define TRAP_divide_error 0
+#define TRAP_debug 1
+#define TRAP_nmi 2
+#define TRAP_int3 3
+#define TRAP_overflow 4
+#define TRAP_bounds 5
+#define TRAP_invalid_op 6
+#define TRAP_no_device 7
+#define TRAP_double_fault 8
+#define TRAP_invalid_tss 10
+#define TRAP_no_segment 11
+#define TRAP_stack_error 12
+#define TRAP_gp_fault 13
+#define TRAP_page_fault 14
+#define TRAP_coproc_error 16
+#define TRAP_alignment_check 17
+#define TRAP_machine_check 18
+#define TRAP_simd_error 19
+#define TRAP_virt_error 20
+#define TRAP_security_error 30
+
+#define ASM_TRAP_SYM(trapname) asm_trap_##trapname
+
+#ifndef __ASSEMBLY__
+
+#define DECLARE_ASM_TRAP(trapname) \
+ void ASM_TRAP_SYM(trapname)(void)
+
+/*
+ * These are assembler stubs in entry.S.
+ * They are the actual entry points for virtual exceptions.
+ */
+DECLARE_ASM_TRAP(divide_error);
+DECLARE_ASM_TRAP(debug);
+DECLARE_ASM_TRAP(nmi);
+DECLARE_ASM_TRAP(int3);
+DECLARE_ASM_TRAP(overflow);
+DECLARE_ASM_TRAP(bounds);
+DECLARE_ASM_TRAP(invalid_op);
+DECLARE_ASM_TRAP(no_device);
+DECLARE_ASM_TRAP(double_fault);
+DECLARE_ASM_TRAP(invalid_tss);
+DECLARE_ASM_TRAP(no_segment);
+DECLARE_ASM_TRAP(stack_error);
+DECLARE_ASM_TRAP(gp_fault);
+DECLARE_ASM_TRAP(page_fault);
+DECLARE_ASM_TRAP(coproc_error);
+DECLARE_ASM_TRAP(alignment_check);
+DECLARE_ASM_TRAP(machine_check);
+DECLARE_ASM_TRAP(simd_error);
+DECLARE_ASM_TRAP(virt_error);
+
+
+void do_unhandled_trap(int trapnr, char *str, struct __regs *regs,
+ unsigned long error_code);
+
+#define DECLARE_TRAP(name, str) \
+void do_##name(struct __regs *regs) \
+{ \
+ do_unhandled_trap(TRAP_##name, str, regs, 0); \
+}
+
+#define DECLARE_TRAP_EC(name, str) \
+void do_##name(struct __regs *regs, unsigned long error_code) \
+{ \
+ do_unhandled_trap(TRAP_##name, str, regs, error_code); \
+}
+
+
+void traps_init(void);
+void traps_fini(void);
+
+#endif
+
+#endif /* __UKARCH_TRAPS_X86_64_H__ */
diff --git a/plat/common/x86/traps.c b/plat/common/x86/traps.c
new file mode 100644
index 0000000..434577f
--- /dev/null
+++ b/plat/common/x86/traps.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+/* Ported from Mini-OS */
+
+#include <uk/arch/lcpu.h>
+#include <trace.h>
+#include <x86/cpu.h>
+#include <x86/traps.h>
+#include <uk/print.h>
+#include <uk/assert.h>
+
+/* Traps handled on both Xen and KVM */
+
+DECLARE_TRAP_EC(divide_error, "divide error")
+DECLARE_TRAP (debug, "debug exception")
+DECLARE_TRAP_EC(int3, "int3")
+DECLARE_TRAP_EC(overflow, "overflow")
+DECLARE_TRAP_EC(bounds, "bounds")
+DECLARE_TRAP_EC(invalid_op, "invalid opcode")
+DECLARE_TRAP_EC(no_device, "device not available")
+DECLARE_TRAP_EC(invalid_tss, "invalid TSS")
+DECLARE_TRAP_EC(no_segment, "segment not present")
+DECLARE_TRAP_EC(stack_error, "stack segment")
+DECLARE_TRAP (coproc_error, "coprocessor error")
+DECLARE_TRAP_EC(alignment_check, "alignment check")
+DECLARE_TRAP_EC(machine_check, "machine check")
+DECLARE_TRAP (simd_error, "SIMD coprocessor error")
+
+
+void do_unhandled_trap(int trapnr, char *str, struct __regs *regs,
+ unsigned long error_code)
+{
+ uk_printd(DLVL_CRIT, "Unhandled Trap %d (%s), error code=0x%lx\n",
+ trapnr, str, error_code);
+ uk_printk("Regs address %p\n", regs);
+ /* TODO revisit when UK_CRASH will also dump the registers */
+ dump_regs(regs);
+ UK_CRASH("Crashing\n");
+}
+
+static int handling_fault;
+
+static void fault_prologue(void)
+{
+ /* If we are already handling a page fault, and got another one
+ * that means we faulted in pagetable walk. Continuing here would cause
+ * a recursive fault
+ */
+ if (handling_fault == 1) {
+ UK_CRASH("Page fault in pagetable walk "
+ "(access to invalid memory?).\n");
+ }
+ handling_fault++;
+ barrier();
+}
+
+void do_gp_fault(struct __regs *regs, long error_code)
+{
+ fault_prologue();
+ uk_printd(DLVL_CRIT, "GPF rip: %lx, error_code=%lx\n",
+ regs->rip, error_code);
+ dump_regs(regs);
+ stack_walk_for_frame(regs->rbp);
+ dump_mem(regs->rsp);
+ dump_mem(regs->rbp);
+ dump_mem(regs->rip);
+ UK_CRASH("Crashing\n");
+}
+
+void do_page_fault(struct __regs *regs, unsigned long error_code)
+{
+ unsigned long addr = read_cr2();
+
+ fault_prologue();
+ uk_printd(DLVL_CRIT, "Page fault at linear address %lx, rip %lx, "
+ "regs %p, sp %lx, our_sp %p, code %lx\n",
+ addr, regs->rip, regs, regs->rsp, &addr, error_code);
+
+ dump_regs(regs);
+ stack_walk_for_frame(regs->rbp);
+ dump_mem(regs->rsp);
+ dump_mem(regs->rbp);
+ dump_mem(regs->rip);
+ UK_CRASH("Crashing\n");
+}
diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk
index 49c4352..55ba50c 100644
--- a/plat/xen/Makefile.uk
+++ b/plat/xen/Makefile.uk
@@ -30,6 +30,7 @@ LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/memory.c
ifneq (,$(filter x86_32 x86_64,$(UK_ARCH)))
LIBXENPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/trace.c|common
+LIBXENPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/traps.c|common
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/setup.c
LIBXENPLAT_SRCS-y += $(LIBXENPLAT_BASE)/x86/traps.c
LIBXENPLAT_SRCS-$(ARCH_X86_32) += $(LIBXENPLAT_BASE)/x86/entry32.S
diff --git a/plat/xen/include/xen-x86/os.h b/plat/xen/include/xen-x86/os.h
index 6fa4fa0..308d91a 100644
--- a/plat/xen/include/xen-x86/os.h
+++ b/plat/xen/include/xen-x86/os.h
@@ -62,32 +62,6 @@ typedef unsigned long u_long;
#include <x86/cpu_defs.h>
-#define __KERNEL_CS FLAT_KERNEL_CS
-#define __KERNEL_DS FLAT_KERNEL_DS
-#define __KERNEL_SS FLAT_KERNEL_SS
-
-#define TRAP_divide_error 0
-#define TRAP_debug 1
-#define TRAP_nmi 2
-#define TRAP_int3 3
-#define TRAP_overflow 4
-#define TRAP_bounds 5
-#define TRAP_invalid_op 6
-#define TRAP_no_device 7
-#define TRAP_double_fault 8
-#define TRAP_copro_seg 9
-#define TRAP_invalid_tss 10
-#define TRAP_no_segment 11
-#define TRAP_stack_error 12
-#define TRAP_gp_fault 13
-#define TRAP_page_fault 14
-#define TRAP_spurious_int 15
-#define TRAP_copro_error 16
-#define TRAP_alignment_check 17
-#define TRAP_machine_check 18
-#define TRAP_simd_error 19
-#define TRAP_deferred_nmi 31
-#define TRAP_xen_callback 32
#define LOCK_PREFIX ""
#define ADDR (*(volatile long *)addr)
@@ -97,8 +71,6 @@ typedef unsigned long u_long;
extern shared_info_t *HYPERVISOR_shared_info;
-void arch_fini(void);
-
#include <xen-x86/irq.h>
@@ -112,12 +84,6 @@ typedef struct {
} atomic_t;
-/********************* common i386 and x86_64 ****************************/
-#define xen_mb() mb()
-#define xen_rmb() rmb()
-#define xen_wmb() wmb()
-#define xen_barrier() asm volatile("" : : : "memory")
-
void block_domain(__snsec until);
#endif /* not assembly */
diff --git a/plat/xen/include/xen-x86/traps.h b/plat/xen/include/xen-x86/traps.h
index 498af76..c585a6e 100644
--- a/plat/xen/include/xen-x86/traps.h
+++ b/plat/xen/include/xen-x86/traps.h
@@ -35,18 +35,23 @@
#ifndef _TRAPS_H_
#define _TRAPS_H_
-#include <x86/regs.h>
+#include <stdint.h>
+#include <x86/traps.h>
-#define pt_regs __regs
+#include <xen/xen.h>
-void dump_regs(struct pt_regs *regs);
-void stack_walk(void);
+#define TRAP_coproc_seg_overrun 9
+#define TRAP_spurious_int 15
+#define TRAP_xen_callback 32
-#define TRAP_PF_PROT 0x1
-#define TRAP_PF_WRITE 0x2
-#define TRAP_PF_USER 0x4
+/* Assembler stubs */
+DECLARE_ASM_TRAP(coproc_seg_overrun);
+DECLARE_ASM_TRAP(spurious_int);
+DECLARE_ASM_TRAP(hypervisor_callback);
+void asm_failsafe_callback(void);
-void trap_init(void);
-void trap_fini(void);
+#define __KERNEL_CS FLAT_KERNEL_CS
+#define __KERNEL_DS FLAT_KERNEL_DS
+#define __KERNEL_SS FLAT_KERNEL_SS
#endif /* _TRAPS_H_ */
diff --git a/plat/xen/x86/arch_time.c b/plat/xen/x86/arch_time.c
index 9e9f1bf..0621d90 100644
--- a/plat/xen/x86/arch_time.c
+++ b/plat/xen/x86/arch_time.c
@@ -235,7 +235,7 @@ void block_domain(__snsec until)
}
static void timer_handler(evtchn_port_t ev __unused,
- struct pt_regs *regs __unused, void *ign __unused)
+ struct __regs *regs __unused, void *ign __unused)
{
__nsec until = ukplat_monotonic_clock() + ukarch_time_msec_to_nsec(1);
diff --git a/plat/xen/x86/entry64.S b/plat/xen/x86/entry64.S
index 8109ccb..db9c615 100644
--- a/plat/xen/x86/entry64.S
+++ b/plat/xen/x86/entry64.S
@@ -25,7 +25,7 @@
#include <uk/arch/types.h>
#include <uk/arch/limits.h>
-#include <x86/regs.h>
+#include <x86/traps.h>
#include <uk/config.h>
#include <xen/xen.h>
#include <xen/elfnote.h>
@@ -115,6 +115,15 @@ KERNEL_CS_MASK = 0xfc
jmp error_entry
.endm
+.macro TRAP_ENTRY trapname, has_ec
+ENTRY(ASM_TRAP_SYM(\trapname))
+.if \has_ec
+ errorentry do_\trapname
+.else
+ zeroentry do_\trapname
+.endif
+.endm
+
.macro RESTORE_ALL
movq OFFSETOF_REGS_R15(%rsp), %r15
movq OFFSETOF_REGS_R14(%rsp), %r14
@@ -194,7 +203,7 @@ error_entry:
/*
* Xen event (virtual interrupt) entry point.
*/
-ENTRY(hypervisor_callback)
+ENTRY(ASM_TRAP_SYM(hypervisor_callback))
zeroentry hypervisor_callback2
hypervisor_callback2:
@@ -250,7 +259,7 @@ ecrit: /**** END OF CRITICAL REGION ****/
hypervisor_prologue:
pushq %r11
pushq %rcx
- jmp hypervisor_callback
+ jmp ASM_TRAP_SYM(hypervisor_callback)
# [How we do the fixup]. We want to merge the current stack frame with the
# just-interrupted frame. How we do this depends on where in the critical
@@ -297,13 +306,10 @@ error_exit:
/*
* Xen event (virtual interrupt) entry point.
*/
-ENTRY(hypervisor_callback)
- zeroentry do_hypervisor_callback
-
-
+TRAP_ENTRY hypervisor_callback, 0
#endif
-ENTRY(failsafe_callback)
+ENTRY(asm_failsafe_callback)
#ifdef CONFIG_PARAVIRT
popq %rcx
popq %r11
@@ -311,72 +317,28 @@ ENTRY(failsafe_callback)
iretq
-ENTRY(coprocessor_error)
- zeroentry do_coprocessor_error
-
-
-ENTRY(simd_coprocessor_error)
- zeroentry do_simd_coprocessor_error
-
-
-ENTRY(device_not_available)
- zeroentry do_device_not_available
-
-
-ENTRY(debug)
- zeroentry do_debug
-
-
-ENTRY(int3)
- zeroentry do_int3
-
-ENTRY(overflow)
- zeroentry do_overflow
-
-
-ENTRY(bounds)
- zeroentry do_bounds
-
-
-ENTRY(invalid_op)
- zeroentry do_invalid_op
-
-
-ENTRY(coprocessor_segment_overrun)
- zeroentry do_coprocessor_segment_overrun
-
-
-ENTRY(invalid_TSS)
- errorentry do_invalid_TSS
-
-
-ENTRY(segment_not_present)
- errorentry do_segment_not_present
-
-
-/* runs on exception stack */
-ENTRY(stack_segment)
- errorentry do_stack_segment
-
-
-ENTRY(general_protection)
- errorentry do_general_protection
-
-
-ENTRY(alignment_check)
- errorentry do_alignment_check
-
-
-ENTRY(divide_error)
- zeroentry do_divide_error
-
-
-ENTRY(spurious_interrupt_bug)
- zeroentry do_spurious_interrupt_bug
-
+TRAP_ENTRY divide_error, 0
+TRAP_ENTRY debug, 0
+/* no NMI */
+TRAP_ENTRY int3, 0
+TRAP_ENTRY overflow, 0
+TRAP_ENTRY bounds, 0
+TRAP_ENTRY invalid_op, 0
+TRAP_ENTRY no_device, 0
+/* no Double Fault */
+TRAP_ENTRY coproc_seg_overrun, 0
+TRAP_ENTRY invalid_tss, 1
+TRAP_ENTRY no_segment, 1
+TRAP_ENTRY stack_error, 1 /* runs on exception stack */
+TRAP_ENTRY gp_fault, 1
+TRAP_ENTRY page_fault, 1
+TRAP_ENTRY spurious_int, 1
+TRAP_ENTRY coproc_error, 0
+TRAP_ENTRY alignment_check, 1
+/* no Machine Check */
+TRAP_ENTRY simd_error, 0
+/* no Virtualization Exception */
-ENTRY(page_fault)
- errorentry do_page_fault
#if HAVE_SCHED
ENTRY(thread_starter)
diff --git a/plat/xen/x86/setup.c b/plat/xen/x86/setup.c
index 21e4786..10f939d 100644
--- a/plat/xen/x86/setup.c
+++ b/plat/xen/x86/setup.c
@@ -113,7 +113,7 @@ struct ukplat_memregion_desc
_libxenplat_mrd[UKPLAT_MEMRD_MAX_ENTRIES];
static inline void _init_traps(void)
{
- trap_init();
+ traps_init();
}
static inline void _init_cpufeatures(void)
diff --git a/plat/xen/x86/traps.c b/plat/xen/x86/traps.c
index da3ca9a..bba3c42 100644
--- a/plat/xen/x86/traps.c
+++ b/plat/xen/x86/traps.c
@@ -23,172 +23,22 @@
*/
/* Taken from Mini-OS */
+#include <stddef.h>
#include <xen-x86/traps.h>
-#include <xen-x86/os.h>
+#include <xen-x86/hypercall.h>
#include <uk/print.h>
-/*
- * These are assembler stubs in entry.S.
- * They are the actual entry points for virtual exceptions.
- */
-void divide_error(void);
-void debug(void);
-void int3(void);
-void overflow(void);
-void bounds(void);
-void invalid_op(void);
-void device_not_available(void);
-void coprocessor_segment_overrun(void);
-void invalid_TSS(void);
-void segment_not_present(void);
-void stack_segment(void);
-void general_protection(void);
-void page_fault(void);
-void coprocessor_error(void);
-void simd_coprocessor_error(void);
-void alignment_check(void);
-void spurious_interrupt_bug(void);
-void machine_check(void);
+/* Traps used only on Xen */
-#define do_exit() \
- for (;;) { \
- }
+DECLARE_TRAP_EC(coproc_seg_overrun, "coprocessor segment overrun")
+DECLARE_TRAP (spurious_int, "spurious interrupt bug")
-static void do_trap(int trapnr, char *str, struct __regs *regs,
- unsigned long error_code)
-{
- uk_printk("FATAL: Unhandled Trap %d (%s), error code=0x%lx\n", trapnr,
- str, error_code);
- uk_printk("Regs address %p\n", regs);
- dump_regs(regs);
-}
-
-#define DO_ERROR(trapnr, str, name)
\
- void do_##name(struct __regs *regs, unsigned long error_code) \
- { \
- do_trap(trapnr, str, regs, error_code); \
- }
-
-#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr)
\
- void do_##name(struct __regs *regs, unsigned long error_code) \
- { \
- do_trap(trapnr, str, regs, error_code); \
- }
-
-DO_ERROR_INFO(0, "divide error", divide_error, FPE_INTDIV, regs->eip)
-DO_ERROR(3, "int3", int3)
-DO_ERROR(4, "overflow", overflow)
-DO_ERROR(5, "bounds", bounds)
-DO_ERROR_INFO(6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
-DO_ERROR(7, "device not available", device_not_available)
-DO_ERROR(9, "coprocessor segment overrun", coprocessor_segment_overrun)
-DO_ERROR(10, "invalid TSS", invalid_TSS)
-DO_ERROR(11, "segment not present", segment_not_present)
-DO_ERROR(12, "stack segment", stack_segment)
-DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR(18, "machine check", machine_check)
-
-static int handling_pg_fault;
-
-void do_page_fault(struct __regs *regs, unsigned long error_code)
-{
- unsigned long addr = read_cr2();
- struct sched_shutdown sched_shutdown = {.reason = SHUTDOWN_crash};
- /* If we are already handling a page fault, and got another one
- * that means we faulted in pagetable walk. Continuing here would cause
- * a recursive fault
- */
- if (handling_pg_fault == 1) {
- uk_printk("Page fault in pagetable walk (access to invalid
memory?).\n");
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- }
- handling_pg_fault++;
- barrier();
-
-#ifdef __X86_64__
- uk_printk("Page fault at linear address %lx, rip %lx, regs %p, sp %lx,
our_sp %p, code %lx\n",
- addr, regs->rip, regs, regs->rsp, &addr, error_code);
-#else
- uk_printk("Page fault at linear address %lx, eip %lx, regs %p, sp %lx,
our_sp %p, code %lx\n",
- addr, regs->eip, regs, regs->esp, &addr, error_code);
-#endif
-
- dump_regs(regs);
-#ifdef __X86_64__
- stack_walk_for_frame(regs->rbp);
- dump_mem(regs->rsp);
- dump_mem(regs->rbp);
- dump_mem(regs->rip);
-#else
- do_stack_walk(regs->ebp);
- dump_mem(regs->esp);
- dump_mem(regs->ebp);
- dump_mem(regs->eip);
-#endif
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- /* We should never get here ... but still */
- handling_pg_fault--;
-}
-
-void do_general_protection(struct __regs *regs, long error_code)
-{
- struct sched_shutdown sched_shutdown = {.reason = SHUTDOWN_crash};
-#ifdef __X86_64__
- uk_printk("GPF rip: %lx, error_code=%lx\n", regs->rip, error_code);
-#else
- uk_printk("GPF eip: %lx, error_code=%lx\n", regs->eip, error_code);
-#endif
- dump_regs(regs);
-#ifdef __X86_64__
- stack_walk_for_frame(regs->rbp);
- dump_mem(regs->rsp);
- dump_mem(regs->rbp);
- dump_mem(regs->rip);
-#else
- do_stack_walk(regs->ebp);
- dump_mem(regs->esp);
- dump_mem(regs->ebp);
- dump_mem(regs->eip);
-#endif
- HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-}
-
-void do_debug(struct __regs *regs)
-{
- uk_printk("Debug exception\n");
-#define TF_MASK 0x100
- regs->eflags &= ~TF_MASK;
- dump_regs(regs);
- do_exit();
-}
-
-void do_coprocessor_error(struct __regs *regs)
-{
- uk_printk("Copro error\n");
- dump_regs(regs);
- do_exit();
-}
-
-void simd_math_error(void *eip __unused)
-{
- uk_printk("SIMD error\n");
-}
-
-void do_simd_coprocessor_error(struct __regs *regs __unused)
-{
- uk_printk("SIMD copro error\n");
-}
-
-void do_spurious_interrupt_bug(struct __regs *regs __unused)
-{
-}
+#ifdef CONFIG_PARAVIRT
-/* Assembler interface fns in entry.S. */
-void hypervisor_callback(void);
-void failsafe_callback(void);
+#define TRAP_TABLE_ENTRY(trapname, pl) \
+ { TRAP_##trapname, pl, __KERNEL_CS, (unsigned long)
ASM_TRAP_SYM(trapname) }
-#ifdef CONFIG_PARAVIRT
/*
* Submit a virtual IDT to teh hypervisor. This consists of tuples
* (interrupt vector, privilege ring, CS:EIP of handler).
@@ -196,41 +46,41 @@ void failsafe_callback(void);
* can trap to that vector using a software-interrupt instruction (INT).
*/
static trap_info_t trap_table[] = {
- { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
- { 1, 0, __KERNEL_CS, (unsigned long)debug },
- { 3, 3, __KERNEL_CS, (unsigned long)int3 },
- { 4, 3, __KERNEL_CS, (unsigned long)overflow },
- { 5, 3, __KERNEL_CS, (unsigned long)bounds },
- { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
- { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
- { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
- { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
- { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
- { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
- { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
- { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
- { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
- { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
- { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
- { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
- { 0, 0, 0, 0 }
+ TRAP_TABLE_ENTRY(divide_error, 0),
+ TRAP_TABLE_ENTRY(debug, 0),
+ TRAP_TABLE_ENTRY(int3, 3),
+ TRAP_TABLE_ENTRY(overflow, 3),
+ TRAP_TABLE_ENTRY(bounds, 3),
+ TRAP_TABLE_ENTRY(invalid_op, 0),
+ TRAP_TABLE_ENTRY(no_device, 0),
+ TRAP_TABLE_ENTRY(coproc_seg_overrun, 0),
+ TRAP_TABLE_ENTRY(invalid_tss, 0),
+ TRAP_TABLE_ENTRY(no_segment, 0),
+ TRAP_TABLE_ENTRY(stack_error, 0),
+ TRAP_TABLE_ENTRY(gp_fault, 0),
+ TRAP_TABLE_ENTRY(page_fault, 0),
+ TRAP_TABLE_ENTRY(spurious_int, 0),
+ TRAP_TABLE_ENTRY(coproc_error, 0),
+ TRAP_TABLE_ENTRY(alignment_check, 0),
+ TRAP_TABLE_ENTRY(simd_error, 0),
+ { 0, 0, 0, 0 }
};
-void trap_init(void)
+void traps_init(void)
{
HYPERVISOR_set_trap_table(trap_table);
#ifdef __i386__
HYPERVISOR_set_callbacks(__KERNEL_CS,
- (unsigned long)hypervisor_callback,
- __KERNEL_CS, (unsigned long)failsafe_callback);
+ (unsigned long) asm_trap_hypervisor_callback,
+ __KERNEL_CS, (unsigned long)
asm_failsafe_callback);
#else
- HYPERVISOR_set_callbacks((unsigned long)hypervisor_callback,
- (unsigned long)failsafe_callback, 0);
+ HYPERVISOR_set_callbacks((unsigned long) asm_trap_hypervisor_callback,
+ (unsigned long) asm_failsafe_callback, 0);
#endif
}
-void trap_fini(void)
+void traps_fini(void)
{
HYPERVISOR_set_trap_table(NULL);
}
@@ -241,12 +91,12 @@ static uint8_t intr_stack[INTR_STACK_SIZE]
__attribute__((aligned(16)));
hw_tss tss __attribute__((aligned(16))) = {
#ifdef __X86_64__
- .rsp0 = (unsigned long)&intr_stack[INTR_STACK_SIZE],
+ .rsp[0] = (unsigned long)&intr_stack[INTR_STACK_SIZE],
#else
.esp0 = (unsigned long)&intr_stack[INTR_STACK_SIZE],
.ss0 = __KERN_DS,
#endif
- .iopb = X86_TSS_INVALID_IO_BITMAP,
+ .iomap_base = X86_TSS_INVALID_IO_BITMAP,
};
static void setup_gate(unsigned int entry, void *addr, unsigned int dpl)
@@ -265,26 +115,28 @@ static void setup_gate(unsigned int entry, void *addr,
unsigned int dpl)
#endif
}
-void trap_init(void)
+void traps_init(void)
{
- setup_gate(TRAP_divide_error, ÷_error, 0);
- setup_gate(TRAP_debug, &debug, 0);
- setup_gate(TRAP_int3, &int3, 3);
- setup_gate(TRAP_overflow, &overflow, 3);
- setup_gate(TRAP_bounds, &bounds, 0);
- setup_gate(TRAP_invalid_op, &invalid_op, 0);
- setup_gate(TRAP_no_device, &device_not_available, 0);
- setup_gate(TRAP_copro_seg, &coprocessor_segment_overrun, 0);
- setup_gate(TRAP_invalid_tss, &invalid_TSS, 0);
- setup_gate(TRAP_no_segment, &segment_not_present, 0);
- setup_gate(TRAP_stack_error, &stack_segment, 0);
- setup_gate(TRAP_gp_fault, &general_protection, 0);
- setup_gate(TRAP_page_fault, &page_fault, 0);
- setup_gate(TRAP_spurious_int, &spurious_interrupt_bug, 0);
- setup_gate(TRAP_copro_error, &coprocessor_error, 0);
- setup_gate(TRAP_alignment_check, &alignment_check, 0);
- setup_gate(TRAP_simd_error, &simd_coprocessor_error, 0);
- setup_gate(TRAP_xen_callback, hypervisor_callback, 0);
+#define SETUP_TRAP_GATE(trapname, dpl) \
+ setup_gate(TRAP_##trapname, &ASM_TRAP_SYM(trapname), dpl)
+ SETUP_TRAP_GATE(divide_error, 0);
+ SETUP_TRAP_GATE(debug, 0);
+ SETUP_TRAP_GATE(int3, 3);
+ SETUP_TRAP_GATE(overflow, 3);
+ SETUP_TRAP_GATE(bounds, 0);
+ SETUP_TRAP_GATE(invalid_op, 0);
+ SETUP_TRAP_GATE(no_device, 0);
+ SETUP_TRAP_GATE(coproc_seg_overrun, 0);
+ SETUP_TRAP_GATE(invalid_tss, 0);
+ SETUP_TRAP_GATE(no_segment, 0);
+ SETUP_TRAP_GATE(stack_error, 0);
+ SETUP_TRAP_GATE(gp_fault, 0);
+ SETUP_TRAP_GATE(page_fault, 0);
+ SETUP_TRAP_GATE(spurious_int, 0);
+ SETUP_TRAP_GATE(coproc_error, 0);
+ SETUP_TRAP_GATE(alignment_check, 0);
+ SETUP_TRAP_GATE(simd_error, 0);
+ setup_gate(TRAP_xen_callback, ASM_TRAP_SYM(hypervisor_callback), 0);
asm volatile("lidt idt_ptr");
@@ -294,12 +146,11 @@ void trap_init(void)
if (hvm_set_parameter(HVM_PARAM_CALLBACK_IRQ,
(2ULL << 56) | TRAP_xen_callback)) {
- uk_printk("Request for Xen HVM callback vector failed\n");
- do_exit();
+ UK_CRASH("Request for Xen HVM callback vector failed\n");
}
}
-void trap_fini(void)
+void traps_fini(void)
{
}
#endif