aboutsummaryrefslogtreecommitdiffstats
path: root/mini-os/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'mini-os/traps.c')
-rw-r--r--mini-os/traps.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/mini-os/traps.c b/mini-os/traps.c
new file mode 100644
index 0000000000..970efdd3a6
--- /dev/null
+++ b/mini-os/traps.c
@@ -0,0 +1,150 @@
+
+#include <os.h>
+#include <hypervisor.h>
+#include <lib.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 double_fault(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);
+
+/*
+ * C handlers here have their parameter-list constructed by the
+ * assembler stubs above. Each one gets a pointer to a list
+ * of register values (to be restored at end of exception).
+ * Some will also receive an error code -- this is the code that
+ * was generated by the processor for the underlying real exception.
+ *
+ * Note that the page-fault exception is special. It also receives
+ * the faulting linear address. Normally this would be found in
+ * register CR2, but that is not accessible in a virtualised OS.
+ */
+
+static void inline do_trap(int trapnr, char *str,
+ struct pt_regs * regs, long error_code)
+{
+ printk("Trap\n");
+}
+
+#define DO_ERROR(trapnr, str, name) \
+void do_##name(struct pt_regs * regs, long error_code) \
+{ \
+ do_trap(trapnr, str, regs, error_code); \
+}
+
+#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
+void do_##name(struct pt_regs * regs, 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( 8, "double fault", double_fault)
+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)
+
+void do_page_fault(struct pt_regs * regs, long error_code,
+ unsigned long address)
+{
+ printk("Page fault\n");
+}
+
+void do_general_protection(struct pt_regs * regs, long error_code)
+{
+ printk("GPF\n");
+}
+
+
+void do_debug(struct pt_regs * regs, long error_code)
+{
+ printk("Debug exception\n");
+#define TF_MASK 0x100
+ regs->eflags &= ~TF_MASK;
+}
+
+
+
+void do_coprocessor_error(struct pt_regs * regs, long error_code)
+{
+ printk("Copro error\n");
+}
+
+void simd_math_error(void *eip)
+{
+ printk("SIMD error\n");
+}
+
+void do_simd_coprocessor_error(struct pt_regs * regs,
+ long error_code)
+{
+ printk("SIMD copro error\n");
+}
+
+void do_spurious_interrupt_bug(struct pt_regs * regs,
+ long error_code)
+{
+}
+
+/*
+ * Submit a virtual IDT to teh hypervisor. This consists of tuples
+ * (interrupt vector, privilege ring, CS:EIP of handler).
+ * The 'privilege ring' field specifies the least-privileged ring that
+ * 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 },
+ { 8, 0, __KERNEL_CS, (unsigned long)double_fault },
+ { 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 },
+ { 18, 0, __KERNEL_CS, (unsigned long)machine_check },
+ { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
+ { 0, 0, 0, 0 }
+};
+
+
+
+void trap_init(void)
+{
+ HYPERVISOR_set_trap_table(trap_table);
+}