diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 8608263..2d9a151 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -3,6 +3,13 @@ #define SYSCALL_NR_READ 0 #define SYSCALL_NR_WRITE 1 +#define SYSCALL_NRX_SIGENTRY 13 +void sys_sigentry(uintptr_t entry); +#define SYSCALL_NR_SIGRETURN 15 +void sys_sigreturn(void); +#define SYSCALL_NRX_SUICIDE 253 +void sys_suicide(void); + #define SYSCALL_NR_FORK 57 int sys_fork(void *ctx); #define SYSCALL_NR_EXIT 60 diff --git a/include/sys/thread.h b/include/sys/thread.h index 0cebdc5..c9083c0 100644 --- a/include/sys/thread.h +++ b/include/sys/thread.h @@ -28,6 +28,9 @@ struct thread { uint64_t sleep_deadline; struct thread *wait_prev, *wait_next; + // Signal + uintptr_t signal_entry; + // State pid_t pid; enum thread_state state; diff --git a/sys/amd64/sched_s.S b/sys/amd64/sched_s.S index 1781fd1..f06a35f 100644 --- a/sys/amd64/sched_s.S +++ b/sys/amd64/sched_s.S @@ -100,3 +100,60 @@ context_switch_first: ret .size context_switch_to, . - context_switch_to + + + + + + + +.global context_sigreturn +context_sigreturn: + movq tmp0(%rip), %rsp + + popq %rbx + popq %rbp + popq %r12 + popq %r13 + popq %r14 + popq %r15 + + ret + + +.global context_sigenter +context_sigenter: + // %rdi - entry + // %rsi - stack + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %rbp + pushq %rbx + + // Use alternate TSS.RSP0 so syscall frame does not get overwritten + movq get_cpu(CPU_THREAD), %rbx + movq %rsp, tmp0(%rip) + movq %rsp, THREAD_RSP0(%rbx) + movq %rsp, THREAD_RSP0_TOP(%rbx) + movq THREAD_RSP0_TOP(%rbx), %rbx + movq get_cpu(CPU_TSS), %r12 + movq %rbx, TSS_RSP0(%r12) + + pushq $0x1B + pushq %rsi + + pushq $0x200 + + pushq $0x23 + pushq %rdi + + iretq + +.section .bss +tmp0: + .quad 0 +// 0xffffff000528df90 +// r15 = 0, r14 = 0, r13 = 0, r12 = 0, +// rbp = 0xffffff000528dfd8, rbx = 0x0 diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index d765b14..d0d0815 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -25,6 +25,10 @@ void *syscall_table[256] = { [SYSCALL_NR_READ] = sys_read, [SYSCALL_NR_WRITE] = sys_write, + [SYSCALL_NRX_SUICIDE] = sys_suicide, + [SYSCALL_NRX_SIGENTRY] = sys_sigentry, + [SYSCALL_NR_SIGRETURN] = sys_sigreturn, + [SYSCALL_NR_EXIT] = sys_exit, [SYSCALL_NR_DEBUG_SLEEP] = sys_debug_sleep, diff --git a/sys/sched.c b/sys/sched.c index 080cd09..4101570 100644 --- a/sys/sched.c +++ b/sys/sched.c @@ -166,6 +166,10 @@ void yield(void) { from->state = THREAD_READY; } + if (to->pid == 1) { + kinfo("%p\n", to->data.rsp0); + } + to->state = THREAD_RUNNING; get_cpu()->thread = to; context_switch_to(to, from); diff --git a/sys/thread.c b/sys/thread.c index 2255d51..a98384a 100644 --- a/sys/thread.c +++ b/sys/thread.c @@ -344,3 +344,32 @@ void thread_sleep(struct thread *thr, uint64_t deadline) { timer_add_sleep(thr); sched_unqueue(thr, THREAD_WAITING); } + +extern void context_sigenter(uintptr_t entry, uintptr_t stack); +extern void context_sigreturn(void); +static char fuck[4096]; + +void sys_sigreturn(void) { + context_sigreturn(); +} + +void sys_suicide(void) { + struct thread *thr = thread_self; + _assert(thr); + kinfo("Enter\n"); + uintptr_t old_rsp0_top = thr->data.rsp0_top; + thr->data.rsp0_top = (uintptr_t) &fuck[4096]; + + context_sigenter(thr->signal_entry, 0x100500); + + thr->data.rsp0_top = old_rsp0_top; + + kinfo("Leave\n"); +} + +void sys_sigentry(uintptr_t entry) { + struct thread *thr = thread_self; + _assert(thr); + + thr->signal_entry = entry; +}