Add a way to handle illegal system call and segmentation faults in
signal handlers
This commit is contained in:
@@ -7,5 +7,5 @@ struct cpu_context;
|
||||
extern uint64_t syscall_count;
|
||||
|
||||
void amd64_syscall_init(void);
|
||||
extern void amd64_syscall_iretq(struct cpu_context *ctx);
|
||||
__attribute__((noreturn)) void amd64_syscall_iretq(struct cpu_context *ctx);
|
||||
__attribute__((noreturn)) void amd64_syscall_yield_stopped(void);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#define SIGINT 2
|
||||
#define SIGQUIT 3
|
||||
#define SIGILL 4
|
||||
#define SIGABRT 6
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGSEGV 11
|
||||
#define SIGSYS 12
|
||||
#define SIGTERM 15
|
||||
|
||||
#define SIGUSR1 16
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#pragma once
|
||||
#if defined(__KERNEL__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned long uint64_t;
|
||||
typedef long int64_t;
|
||||
typedef int sig_atomic_t;
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *) 0)
|
||||
|
||||
+22
-3
@@ -1,7 +1,9 @@
|
||||
#include "sys/amd64/mm/map.h"
|
||||
#include "sys/amd64/syscall.h"
|
||||
#include "sys/amd64/cpu.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/thread.h"
|
||||
#include "sys/signum.h"
|
||||
#include "sys/debug.h"
|
||||
|
||||
extern void amd64_syscall_yield_stopped();
|
||||
@@ -23,6 +25,7 @@ int amd64_pfault(uintptr_t cr2) {
|
||||
thr->pid);
|
||||
|
||||
kerror("CR2 = %p\n", cr2);
|
||||
kerror("RIP = %p\n", ctx->rip);
|
||||
|
||||
// Dump registers
|
||||
cpu_print_context(DEBUG_ERROR, ctx);
|
||||
@@ -35,9 +38,25 @@ int amd64_pfault(uintptr_t cr2) {
|
||||
// because they're presumably fucked up by error code
|
||||
// push
|
||||
|
||||
thr->flags |= THREAD_STOPPED;
|
||||
amd64_syscall_yield_stopped();
|
||||
return -1;
|
||||
// The whole thread context is on the stack
|
||||
|
||||
if (thr->pid > 0) {
|
||||
thread_signal(thr, SIGSEGV);
|
||||
|
||||
// Suicide signal, just hang on and wait
|
||||
// until scheduler decides it's our time
|
||||
while (thr->sigq) {
|
||||
asm volatile ("sti; hlt; cli");
|
||||
}
|
||||
|
||||
amd64_syscall_iretq(ctx);
|
||||
} else {
|
||||
panic("Segmentation fault happened in kernel thread\n");
|
||||
}
|
||||
|
||||
//thr->flags |= THREAD_STOPPED;
|
||||
//amd64_syscall_yield_stopped();
|
||||
//return -1;
|
||||
}
|
||||
|
||||
void amd64_pfault_kernel(uintptr_t rip, uintptr_t cr2) {
|
||||
|
||||
+5
-11
@@ -14,9 +14,12 @@ amd64_exc_isr_14:
|
||||
// rip
|
||||
swapgs_if_needed
|
||||
|
||||
// Fuck error code
|
||||
addq $8, %rsp
|
||||
|
||||
pushq %rax
|
||||
movq $(1 << 63), %rax
|
||||
testq %rax, 16(%rsp)
|
||||
testq %rax, 8(%rsp)
|
||||
jnz _pfault_kernel
|
||||
popq %rax
|
||||
|
||||
@@ -38,16 +41,7 @@ amd64_exc_isr_14:
|
||||
|
||||
movq %cr2, %rdi
|
||||
call amd64_pfault
|
||||
|
||||
// If fault handler returned zero, it means next task is selected
|
||||
// and should be run
|
||||
test %rax, %rax
|
||||
jnz 1f
|
||||
|
||||
// Ok, continue
|
||||
|
||||
|
||||
// Fail
|
||||
// Failed to handle the fault
|
||||
1:
|
||||
cli
|
||||
hlt
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "sys/amd64/syscall.h"
|
||||
#include "sys/amd64/cpu.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/signum.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/thread.h"
|
||||
#include "sys/debug.h"
|
||||
@@ -138,3 +139,19 @@ gid_t sys_getgid(void) {
|
||||
_assert(thr);
|
||||
return thr->ioctx.gid;
|
||||
}
|
||||
|
||||
int sys_unknown(int no) {
|
||||
asm volatile ("cli");
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
_assert(thr);
|
||||
|
||||
thread_signal(thr, SIGSYS);
|
||||
|
||||
// Suicide signal, just hang on and wait
|
||||
// until scheduler decides it's our time
|
||||
while (thr->sigq) {
|
||||
asm volatile ("sti; hlt; cli");
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,5 @@ const void *amd64_syscall_jmp_table[256] = {
|
||||
|
||||
// Memory
|
||||
[SYSCALL_NR_BRK] = sys_brk,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -76,15 +76,15 @@ amd64_syscall_entry:
|
||||
movq %r10, %rcx
|
||||
incq syscall_count(%rip)
|
||||
leaq amd64_syscall_jmp_table(%rip), %r10
|
||||
movq (%r10, %rax, 8), %rax
|
||||
test %rax, %rax
|
||||
movq (%r10, %rax, 8), %r10
|
||||
test %r10, %r10
|
||||
jz 1f
|
||||
sti
|
||||
call *%rax
|
||||
call *%r10
|
||||
jmp 2f
|
||||
1:
|
||||
// -EINVAL
|
||||
mov $-22, %rax
|
||||
movq %rax, %rdi
|
||||
call sys_unknown
|
||||
2:
|
||||
//movq %rax, %r9
|
||||
//call amd64_syscall
|
||||
|
||||
@@ -307,7 +307,6 @@ static int vfs_find_internal(struct vfs_ioctx *ctx, struct vnode *at, const char
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: lookup_or_load
|
||||
if ((err = vfs_lookup_or_load(at, name, &node)) != 0) {
|
||||
kdebug("miss %s in %s\n", name, at->name);
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user