summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/cpu/idt.c13
-rw-r--r--kernel/cpu/isr.s9
-rw-r--r--kernel/includes/signal.h1
-rw-r--r--kernel/sched/scheduler.c11
-rw-r--r--kernel/sched/scheduler.h1
5 files changed, 28 insertions, 7 deletions
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 9508f8c..acede33 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -76,6 +76,13 @@ void page_fault(reg_t *regs) {
process_pop_restore_context(NULL, regs);
return;
}
+
+ int is_userspace = (regs->error_code & (1 << 2));
+ if (is_userspace) {
+ signal_process(current_task, SIGSEGV);
+ return;
+ }
+
klog("Page Fault", LOG_ERROR);
kprintf("CR2: %x\n", cr2);
if (current_task) {
@@ -97,15 +104,11 @@ void page_fault(reg_t *regs) {
kprintf("read access\n");
}
- if (regs->error_code & (1 << 2)) {
- kprintf("CPL = 3\n");
- }
-
if (regs->error_code & (1 << 4)) {
kprintf("Attempted instruction fetch\n");
}
- dump_backtrace(20);
+ dump_backtrace(15);
halt();
}
diff --git a/kernel/cpu/isr.s b/kernel/cpu/isr.s
index 8032485..819b22b 100644
--- a/kernel/cpu/isr.s
+++ b/kernel/cpu/isr.s
@@ -11,6 +11,13 @@
push \num
jmp isr_common_stub
.endm
+.macro ISR_ERRCODE num
+ .global isr\num
+ isr\num:
+ cli
+ push \num
+ jmp isr_common_stub
+.endm
ISR_NOERRCODE 0
ISR_NOERRCODE 1
@@ -26,7 +33,7 @@ ISR_NOERRCODE 10
ISR_NOERRCODE 11
ISR_NOERRCODE 12
ISR_NOERRCODE 13
-ISR_NOERRCODE 14
+ISR_ERRCODE 14
ISR_NOERRCODE 15
ISR_NOERRCODE 16
ISR_NOERRCODE 17
diff --git a/kernel/includes/signal.h b/kernel/includes/signal.h
index b9ab4a7..6bc9f67 100644
--- a/kernel/includes/signal.h
+++ b/kernel/includes/signal.h
@@ -6,6 +6,7 @@
#define SIGWINCH 2
#define SIGQUIT 3
#define SIG_IGN 4
+#define SIGSEGV 5
#define SIGTERM 15
typedef int sigset_t;
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index 423c1b6..57ab33b 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -216,6 +216,7 @@ void free_process(process_t *p) {
void exit_process(process_t *p, int status) {
disable_interrupts();
+ int killing_itself = (p == current_task);
assert(p->pid != 1);
if (p->parent) {
p->parent->halts[WAIT_CHILD_HALT] = 0;
@@ -246,6 +247,9 @@ void exit_process(process_t *p, int status) {
}
tmp = tmp->next;
}
+ if (killing_itself) {
+ switch_task();
+ }
}
void exit(int status) {
@@ -474,9 +478,14 @@ void signal_process(process_t *p, int sig) {
if (SIGTERM == sig) {
kprintf("HAS NO SIGTERM\n");
exit_process(p, 1 /*TODO: what should the status be?*/);
+ ASSERT_NOT_REACHED;
+ } else if (SIGSEGV == sig) {
+ kprintf("HAS NO SIGSEGV\n");
+ exit_process(p, 1 /*TODO: what should the status be?*/);
+ ASSERT_NOT_REACHED;
} else {
// TODO: Should also exit proess(I think)
- assert(0);
+ ASSERT_NOT_REACHED;
}
}
signal_t signal = {.handler_ip = (uintptr_t)p->signal_handlers[sig]};
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index b197117..7e42cc7 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -98,4 +98,5 @@ struct Process {
int get_task_from_pid(pid_t pid, process_t **out);
void free_process(process_t *p);
void *get_free_virtual_memory(size_t length);
+void signal_process(process_t *p, int sig);
#endif