summaryrefslogtreecommitdiff
path: root/kern/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/interrupt.c')
-rw-r--r--kern/interrupt.c172
1 files changed, 125 insertions, 47 deletions
diff --git a/kern/interrupt.c b/kern/interrupt.c
index e3c2c64..467c7c9 100644
--- a/kern/interrupt.c
+++ b/kern/interrupt.c
@@ -25,6 +25,7 @@
#include <interrupt.h>
#include <mm.h>
#include <paging.h>
+#include <pv.h>
#include <sched.h>
#include <sync.h>
#include <timer.h>
@@ -55,6 +56,8 @@
/** EIP's low part's bits */
#define IDT_EIP_LO_MASK 0x0000ffff
+#define IDT_FAULT_15 15
+
/**
* @brief an idt entry
*/
@@ -139,6 +142,10 @@ int gp_handler();
*/
int pf_handler();
/**
+ * @brief Fault 15 entry
+ */
+int fault_15_handler();
+/**
* @brief MF handler entry
*/
int mf_handler();
@@ -270,10 +277,38 @@ void sys_readfile();
*/
void sys_swexn();
+void sys_67();
+void sys_86();
+void sys_97();
+void sys_99();
+void sys_100();
+void sys_101();
+void sys_102();
+void sys_103();
+void sys_104();
+void sys_105();
+void sys_106();
+void sys_107();
+void sys_108();
+void sys_109();
+void sys_110();
+void sys_111();
+void sys_112();
+void sys_113();
+void sys_114();
+void sys_115();
+void sys_128();
+void sys_129();
+void sys_130();
+void sys_131();
+void sys_132();
+void sys_133();
+void sys_134();
+
/**
* @brief all other syscall entries
*/
-void sys_enosys();
+void sys_nonexist();
void sys_hvcall();
@@ -303,6 +338,8 @@ void idt_init() {
idt[IDT_SS] = make_idt((va_t)ss_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
idt[IDT_GP] = make_idt((va_t)gp_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
idt[IDT_PF] = make_idt((va_t)pf_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
+ idt[IDT_FAULT_15] =
+ make_idt((va_t)fault_15_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
idt[IDT_MF] = make_idt((va_t)mf_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
idt[IDT_AC] = make_idt((va_t)ac_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
idt[IDT_MC] = make_idt((va_t)mc_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
@@ -314,11 +351,12 @@ void idt_init() {
make_idt((va_t)kbd_handler, IDT_TYPE_I32, IDT_DPL_KERNEL);
for (i = IDT_SYSCALL_START; i < IDT_ENTS; i++) {
- idt[i] = make_idt((va_t)sys_enosys, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[i] = make_idt((va_t)sys_nonexist, IDT_TYPE_T32, IDT_DPL_USER);
}
idt[FORK_INT] = make_idt((va_t)sys_fork, IDT_TYPE_T32, IDT_DPL_USER);
idt[EXEC_INT] = make_idt((va_t)sys_exec, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[67] = make_idt((va_t)sys_67, IDT_TYPE_T32, IDT_DPL_USER);
idt[WAIT_INT] = make_idt((va_t)sys_wait, IDT_TYPE_T32, IDT_DPL_USER);
idt[YIELD_INT] = make_idt((va_t)sys_yield, IDT_TYPE_T32, IDT_DPL_USER);
idt[DESCHEDULE_INT] =
@@ -348,15 +386,42 @@ void idt_init() {
idt[MISBEHAVE_INT] =
make_idt((va_t)sys_misbehave, IDT_TYPE_T32, IDT_DPL_USER);
idt[HALT_INT] = make_idt((va_t)sys_halt, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[86] = make_idt((va_t)sys_86, IDT_TYPE_T32, IDT_DPL_USER);
idt[TASK_VANISH_INT] =
make_idt((va_t)sys_task_vanish, IDT_TYPE_T32, IDT_DPL_USER);
idt[SET_STATUS_INT] =
make_idt((va_t)sys_set_status, IDT_TYPE_T32, IDT_DPL_USER);
idt[VANISH_INT] = make_idt((va_t)sys_vanish, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[97] = make_idt((va_t)sys_97, IDT_TYPE_T32, IDT_DPL_USER);
idt[READFILE_INT] =
make_idt((va_t)sys_readfile, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[99] = make_idt((va_t)sys_99, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[100] = make_idt((va_t)sys_100, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[101] = make_idt((va_t)sys_101, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[102] = make_idt((va_t)sys_102, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[103] = make_idt((va_t)sys_103, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[104] = make_idt((va_t)sys_104, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[105] = make_idt((va_t)sys_105, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[106] = make_idt((va_t)sys_106, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[107] = make_idt((va_t)sys_107, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[108] = make_idt((va_t)sys_108, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[109] = make_idt((va_t)sys_109, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[110] = make_idt((va_t)sys_110, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[111] = make_idt((va_t)sys_111, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[112] = make_idt((va_t)sys_112, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[113] = make_idt((va_t)sys_113, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[114] = make_idt((va_t)sys_114, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[115] = make_idt((va_t)sys_115, IDT_TYPE_T32, IDT_DPL_USER);
idt[SWEXN_INT] = make_idt((va_t)sys_swexn, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[128] = make_idt((va_t)sys_128, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[129] = make_idt((va_t)sys_129, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[130] = make_idt((va_t)sys_130, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[131] = make_idt((va_t)sys_131, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[132] = make_idt((va_t)sys_132, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[133] = make_idt((va_t)sys_133, IDT_TYPE_T32, IDT_DPL_USER);
+ idt[134] = make_idt((va_t)sys_134, IDT_TYPE_T32, IDT_DPL_USER);
+
idt[HV_INT] = make_idt((va_t)sys_hvcall, IDT_TYPE_T32, IDT_DPL_USER);
}
@@ -401,6 +466,8 @@ const static char* reasons[] = {"Division Error",
static void dump_fault(ureg_t* frame);
static int handle_zfod(ureg_t* frame, thread_t* t);
+static void handle_kernel_fault(ureg_t* frame, thread_t* t);
+static void handle_user_fault(ureg_t* frame, thread_t* t);
/**
* @brief handle a fault
@@ -414,22 +481,57 @@ void handle_fault(ureg_t* frame) {
return;
}
}
- if (frame->cs == SEGSEL_KERNEL_CS) {
- /* recover from accessing user memory */
- if ((frame->cause == SWEXN_CAUSE_PAGEFAULT ||
- frame->cause == SWEXN_CAUSE_PROTFAULT) &&
- current->eip0 != 0) {
- frame->eip = current->eip0;
- return;
- }
- /* all other non recoverable fault */
- dump_fault(frame);
- while (1) {
+ if (frame->cs == SEGSEL_PV_CS) {
+ pv_handle_fault(frame, current);
+ return;
+ } else if (frame->cs == SEGSEL_KERNEL_CS) {
+ handle_kernel_fault(frame, current);
+ return;
+ }
+ handle_user_fault(frame, current);
+}
+
+static int handle_zfod(ureg_t* frame, thread_t* t) {
+ int result = -1;
+ process_t* p = t->process;
+ int old_if = save_clear_if();
+ pa_t old_pa;
+ page_directory_t* pd = (page_directory_t*)map_phys_page(p->cr3, &old_pa);
+ pde_t* pde = &(*pd)[get_pd_index(frame->cr2)];
+ if (*pde != BAD_PDE) {
+ pa_t pt_pa = get_page_table(*pde);
+ page_table_t* pt = (page_table_t*)map_phys_page(pt_pa, NULL);
+ pte_t* pte = &(*pt)[get_pt_index(frame->cr2)];
+ if (*pte != BAD_PTE && ((*pte & (PTE_PRESENT << PTE_P_SHIFT)) == 0)) {
+ *pte = (*pte | (PTE_PRESENT << PTE_P_SHIFT));
+ invlpg(frame->cr2);
+ memset((void*)(frame->cr2 & PAGE_BASE_MASK), 0, PAGE_SIZE);
+ result = 0;
}
}
+ map_phys_page(old_pa, NULL);
+ restore_if(old_if);
+ return result;
+}
+
+static void handle_kernel_fault(ureg_t* frame, thread_t* t) {
+ /* recover from accessing user memory */
+ if ((frame->cause == SWEXN_CAUSE_PAGEFAULT ||
+ frame->cause == SWEXN_CAUSE_PROTFAULT) &&
+ t->eip0 != 0) {
+ frame->eip = t->eip0;
+ return;
+ }
+ /* all other non recoverable fault */
+ dump_fault(frame);
+ while (1) {
+ }
+}
+
+static void handle_user_fault(ureg_t* frame, thread_t* t) {
/* send to user swexn */
- if (current->eip3 != 0 && current->df3 == 0) {
- va_t esp3 = (va_t)current->esp3;
+ if (t->eip3 != 0 && t->df3 == 0) {
+ va_t esp3 = (va_t)t->esp3;
esp3 -= sizeof(ureg_t);
esp3 = (esp3 & (~(sizeof(va_t) - 1)));
/* push ureg */
@@ -440,7 +542,7 @@ void handle_fault(ureg_t* frame) {
* swexn handler must call swexn to jump back, we use 0 address to cause
* a GP on function return
*/
- unsigned long stack[3] = {0, current->swexn_arg, (unsigned long)esp3};
+ unsigned long stack[3] = {0, t->swexn_arg, (unsigned long)esp3};
unsigned long* new_esp = (unsigned long*)esp3;
new_esp -= 3;
if (copy_to_user((va_t)new_esp, 3 * sizeof(unsigned long), stack) !=
@@ -455,47 +557,23 @@ void handle_fault(ureg_t* frame) {
frame->edx = 0;
frame->ecx = 0;
frame->eax = 0;
- frame->eip = current->eip3;
+ frame->eip = t->eip3;
frame->eflags = DEFAULT_EFLAGS;
frame->esp = (unsigned int)new_esp;
- current->df3 = 1;
- current->eip3 = 0;
+ t->df3 = 1;
+ t->eip3 = 0;
return;
}
/* no swexn handler or fault inside swexn */
kill_thread:
- sim_printf("LWP %d killed: %s", current->rb_node.key,
- reasons[frame->cause]);
- printf("LWP %d killed: %s\n", current->rb_node.key, reasons[frame->cause]);
- if (current->process->refcount == 1) {
- current->process->exit_value = -2;
+ sim_printf("LWP %d killed: %s", t->rb_node.key, reasons[frame->cause]);
+ printf("LWP %d killed: %s\n", t->rb_node.key, reasons[frame->cause]);
+ if (t->process->refcount == 1) {
+ t->process->exit_value = -2;
}
kill_current();
}
-static int handle_zfod(ureg_t* frame, thread_t* t) {
- int result = -1;
- process_t* p = t->process;
- int old_if = save_clear_if();
- pa_t old_pa;
- page_directory_t* pd = (page_directory_t*)map_phys_page(p->cr3, &old_pa);
- pde_t* pde = &(*pd)[get_pd_index(frame->cr2)];
- if (*pde != BAD_PDE) {
- pa_t pt_pa = get_page_table(*pde);
- page_table_t* pt = (page_table_t*)map_phys_page(pt_pa, NULL);
- pte_t* pte = &(*pt)[get_pt_index(frame->cr2)];
- if (*pte != BAD_PTE && ((*pte & (PTE_PRESENT << PTE_P_SHIFT)) == 0)) {
- *pte = (*pte | (PTE_PRESENT << PTE_P_SHIFT));
- invlpg(frame->cr2);
- memset((void*)(frame->cr2 & PAGE_BASE_MASK), 0, PAGE_SIZE);
- result = 0;
- }
- }
- map_phys_page(old_pa, NULL);
- restore_if(old_if);
- return result;
-}
-
static void dump_fault(ureg_t* frame) {
sim_printf("Fault: %s Error Code: %08x", reasons[frame->cause],
frame->error_code);