Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios-OLD.git] / kitten / arch / x86_64 / kernel / interrupts.c
diff --git a/kitten/arch/x86_64/kernel/interrupts.c b/kitten/arch/x86_64/kernel/interrupts.c
new file mode 100644 (file)
index 0000000..ff55da3
--- /dev/null
@@ -0,0 +1,333 @@
+#include <lwk/kernel.h>
+#include <lwk/init.h>
+#include <lwk/kallsyms.h>
+#include <lwk/task.h>
+#include <lwk/sched.h>
+#include <lwk/timer.h>
+#include <lwk/palacios.h>
+#include <arch/desc.h>
+#include <arch/idt_vectors.h>
+#include <arch/show.h>
+#include <arch/xcall.h>
+#include <arch/i387.h>
+#include <arch/io.h>
+
+idtvec_handler_t idtvec_table[NUM_IDT_ENTRIES];
+static DEFINE_SPINLOCK(idtvec_table_lock);
+
+extern void asm_idtvec_table(void);
+
+void
+do_unhandled_idt_vector(struct pt_regs *regs, unsigned int vector)
+{
+       if ((vector >= IRQ0_VECTOR) && (vector <= IRQ15_VECTOR)) {
+               printk(KERN_EMERG
+                      "Unhandled Interrupt! (vector=%u, isa_irq=%u)\n",
+                      vector, vector - IRQ0_VECTOR);
+       } else {
+               printk(KERN_EMERG
+                      "Unhandled Interrupt! (vector=%u)\n", vector);
+       }
+}
+
+void
+do_divide_error(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Divide Error Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_nmi(struct pt_regs *regs, unsigned int vector)
+{
+       printk("NMI Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_int3(struct pt_regs *regs, unsigned int vector)
+{
+       printk("INT3 Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_overflow(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Overflow Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_bounds(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Bounds Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_invalid_op(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Invalid Op Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_device_not_available(struct pt_regs *regs, unsigned int vector)
+{
+       BUG_ON(current->arch.flags & TF_USED_FPU);
+       current->arch.flags |= TF_USED_FPU;
+       clts();
+       fpu_restore_state(current);
+}
+
+void
+do_double_fault(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Double Fault Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_coproc_segment_overrun(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Coprocessor Segment Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_invalid_tss(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Invalid TSS Exception)\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_segment_not_present(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Segment Not Present Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_stack_segment(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Stack Segment Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_general_protection(struct pt_regs *regs, unsigned int vector)
+{
+       printk("General Protection Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_page_fault(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Page Fault Exception (regs %p)\n", regs );
+
+       static uint8_t recursive_fault;
+       if( recursive_fault++ )
+               panic( "Recursive page fault!  Halt and catch fire!" );
+
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_spurious_interrupt_bug(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Spurious Interrupt Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_coprocessor_error(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Coprocessor Error Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_alignment_check(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Alignment Check Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_machine_check(struct pt_regs *regs, unsigned int vector)
+{
+       printk("Machine Check Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_simd_coprocessor_error(struct pt_regs *regs, unsigned int vector)
+{
+       printk("SIMD Coprocessor Error Exception\n");
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_apic_timer(struct pt_regs *regs, unsigned int vector)
+{
+       expire_timers();
+}
+
+void
+do_apic_perf_counter(struct pt_regs *regs, unsigned int vector)
+{
+       printk("APIC Perf. Counter Interrupt, vector=%u\n", vector);
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_apic_thermal(struct pt_regs *regs, unsigned int vector)
+{
+       printk("APIC Thermal Interrupt, vector=%u\n", vector);
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_apic_error(struct pt_regs *regs, unsigned int vector)
+{
+       printk("APIC Error Interrupt, vector=%u\n", vector);
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_apic_spurious(struct pt_regs *regs, unsigned int vector)
+{
+       printk("APIC Spurious Interrupt, vector=%u\n", vector);
+       show_registers(regs);
+       while (1) {}
+}
+
+void
+do_keyboard_interrupt(struct pt_regs *regs, unsigned int vector)
+{
+       const uint8_t KB_OUTPUT_FULL = 0x01;
+       const uint8_t KB_STATUS_PORT = 0x64;
+       const uint8_t KB_DATA_PORT = 0x60;
+
+       uint8_t status = inb( KB_STATUS_PORT );
+
+       if( (status & KB_OUTPUT_FULL) == 0 )
+               return;
+
+       uint8_t key = inb( KB_DATA_PORT );
+#ifdef CONFIG_V3VEE
+       send_key_to_vmm( status, key );
+#endif
+}
+
+
+void
+set_idtvec_handler(unsigned int vector, idtvec_handler_t handler)
+{
+       char namebuf[KSYM_NAME_LEN+1];
+       unsigned long symsize, offset;
+       unsigned long irqstate;
+
+       ASSERT(vector < NUM_IDT_ENTRIES);
+
+       if (handler != &do_unhandled_idt_vector) {
+               printk(KERN_DEBUG "IDT Vector %3u -> %s()\n",
+                       vector, kallsyms_lookup( (unsigned long)handler,
+                                                 &symsize, &offset, namebuf )
+               );
+       }
+
+       spin_lock_irqsave(&idtvec_table_lock, irqstate);
+       idtvec_table[vector] = handler;
+       spin_unlock_irqrestore(&idtvec_table_lock, irqstate);
+}
+
+void
+do_interrupt(struct pt_regs *regs, unsigned int vector)
+{
+       idtvec_table[vector](regs, vector);
+       if (vector >= FIRST_EXTERNAL_VECTOR)
+               lapic_ack_interrupt();
+}
+
+void __init
+interrupts_init(void)
+{
+       int vector;
+
+       /*
+        * Initialize the Interrupt Descriptor Table (IDT).
+        */
+       for (vector = 0; vector < NUM_IDT_ENTRIES; vector++) {
+               void *asm_handler = (void *) (
+                 (uintptr_t)(&asm_idtvec_table) + (vector * 16)
+               );
+               set_intr_gate(vector, asm_handler);
+               set_idtvec_handler(vector, &do_unhandled_idt_vector);
+       }
+
+       /*
+        * Register handlers for the standard x86_64 interrupts & exceptions.
+        */
+       set_idtvec_handler( DIVIDE_ERROR_VECTOR,           &do_divide_error           );
+       set_idtvec_handler( NMI_VECTOR,                    &do_nmi                    );
+       set_idtvec_handler( INT3_VECTOR,                   &do_int3                   );
+       set_idtvec_handler( OVERFLOW_VECTOR,               &do_overflow               );
+       set_idtvec_handler( BOUNDS_VECTOR,                 &do_bounds                 );
+       set_idtvec_handler( INVALID_OP_VECTOR,             &do_invalid_op             );
+       set_idtvec_handler( DEVICE_NOT_AVAILABLE_VECTOR,   &do_device_not_available   );
+       set_idtvec_handler( DOUBLE_FAULT_VECTOR,           &do_double_fault           );
+       set_idtvec_handler( COPROC_SEGMENT_OVERRUN_VECTOR, &do_coproc_segment_overrun );
+       set_idtvec_handler( INVALID_TSS_VECTOR,            &do_invalid_tss            );
+       set_idtvec_handler( SEGMENT_NOT_PRESENT_VECTOR,    &do_segment_not_present    );
+       set_idtvec_handler( STACK_SEGMENT_VECTOR,          &do_stack_segment          );
+       set_idtvec_handler( GENERAL_PROTECTION_VECTOR,     &do_general_protection     );
+       set_idtvec_handler( PAGE_FAULT_VECTOR,             &do_page_fault             );
+       set_idtvec_handler( SPURIOUS_INTERRUPT_BUG_VECTOR, &do_spurious_interrupt_bug );
+       set_idtvec_handler( COPROCESSOR_ERROR_VECTOR,      &do_coprocessor_error      );
+       set_idtvec_handler( ALIGNMENT_CHECK_VECTOR,        &do_alignment_check        );
+       set_idtvec_handler( MACHINE_CHECK_VECTOR,          &do_machine_check          );
+       set_idtvec_handler( SIMD_COPROCESSOR_ERROR_VECTOR, &do_simd_coprocessor_error );
+       set_idtvec_handler( IRQ1_VECTOR, &do_keyboard_interrupt );
+
+       /*
+        * Register handlers for all of the local APIC vectors.
+        */
+       set_idtvec_handler( APIC_TIMER_VECTOR,        &do_apic_timer        );
+       set_idtvec_handler( APIC_PERF_COUNTER_VECTOR, &do_apic_perf_counter );
+       set_idtvec_handler( APIC_THERMAL_VECTOR,      &do_apic_thermal      );
+       set_idtvec_handler( APIC_ERROR_VECTOR,        &do_apic_error        );
+       set_idtvec_handler( APIC_SPURIOUS_VECTOR,     &do_apic_spurious     );
+
+       /*
+        * Register handlers for inter-CPU interrupts (cross calls).
+        */
+       set_idtvec_handler( XCALL_FUNCTION_VECTOR,   &arch_xcall_function_interrupt   );
+       set_idtvec_handler( XCALL_RESCHEDULE_VECTOR, &arch_xcall_reschedule_interrupt );
+}
+
+