Unifying External Interrupt System (#51)
[lunaix-os.git] / lunaix-os / arch / x86 / exceptions / interrupts.c
index ceb3853150578fa1fb8cf28a3d583bc7a81eef7b..9941a5c20940aa8fe21ee27cf813efab8e5ac2c1 100644 (file)
@@ -5,11 +5,28 @@
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/syslog.h>
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/syslog.h>
+#include <lunaix/failsafe.h>
 
 
-#include <asm/x86_isrm.h>
+#include <hal/irq.h>
 
 LOG_MODULE("INTR")
 
 
 LOG_MODULE("INTR")
 
+extern void
+intr_routine_page_fault(const struct hart_state* state);
+
+extern void
+syscall_hndlr(const struct hart_state* hstate);
+
+extern void
+apic_ack_interrupt(irq_t irq);
+
+static void noret
+__set_panic(const char* msg, const struct hart_state* state)
+{
+    ERROR("panic: %s", msg);
+    failsafe_diagnostic();
+}
+
 static inline void
 update_thread_context(struct hart_state* state)
 {
 static inline void
 update_thread_context(struct hart_state* state)
 {
@@ -26,23 +43,83 @@ update_thread_context(struct hart_state* state)
     }
 }
 
     }
 }
 
+
+static bool
+__handle_internal_vectors(const struct hart_state* state)
+{
+    switch (hart_vector_stamp(state))
+    {
+    case FAULT_DIVISION_ERROR:
+        __set_panic("div zero", state);
+        break;
+
+    case FAULT_GENERAL_PROTECTION:
+        __set_panic("general protection", state);
+        break;
+
+    case FAULT_PAGE_FAULT:
+        intr_routine_page_fault(state);
+        break;
+
+    case FAULT_INVALID_OPCODE:
+        __set_panic("invalid opcode", state);;
+        break;
+
+    case LUNAIX_SCHED:
+        apic_ack_interrupt(NULL);
+        schedule();
+        break;
+
+    case APIC_SPIV_IV:
+        break;
+
+    case APIC_ERROR_IV:
+        __set_panic("apic error", state);;
+        break;
+
+    case LUNAIX_SYS_CALL:
+        syscall_hndlr(state);
+        break;
+    
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+static bool
+__handle_external_irq(const struct hart_state* state)
+{
+    irq_t irq;
+    int ex_iv;
+
+    ex_iv = hart_vector_stamp(state);
+    irq   = irq_find(irq_get_default_domain(), ex_iv);
+
+    if (unlikely(!irq)) {
+        return false;
+    }
+
+    irq_serve(irq, state);
+    apic_ack_interrupt(irq);
+    return true;
+}
+
 struct hart_state*
 intr_handler(struct hart_state* state)
 {
     update_thread_context(state);
 
     volatile struct exec_param* execp = state->execp;
 struct hart_state*
 intr_handler(struct hart_state* state)
 {
     update_thread_context(state);
 
     volatile struct exec_param* execp = state->execp;
-    if (execp->vector <= 255) {
-        isr_cb subscriber = isrm_get(execp->vector);
-        subscriber(state);
-        goto done;
+    
+    if (__handle_internal_vectors(state)) {
+        return state;
     }
 
     }
 
-done:
-
-    if (execp->vector > IV_BASE_END) {
-        isrm_notify_eoi(0, execp->vector);
+    if (__handle_external_irq(state)) {
+        return state;
     }
 
     }
 
-    return state;
+    __set_panic("unknown interrupt", state);
 }
\ No newline at end of file
 }
\ No newline at end of file