From 9729e5a05b1b0b68dfd854ef6ca6dbbc0b53591f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 23 Jul 2023 18:33:10 +0300 Subject: [PATCH] Kernel: Change signal kernel API return rsp and rip are now stored per thread --- kernel/arch/x86_64/IDT.cpp | 17 +++++++++++++++-- kernel/arch/x86_64/interrupts.S | 6 ++++++ kernel/include/kernel/Process.h | 4 ++-- kernel/include/kernel/Thread.h | 9 ++++++++- kernel/kernel/Process.cpp | 22 +++++++++++++++------- kernel/kernel/Syscall.cpp | 6 ++++-- kernel/kernel/Thread.cpp | 27 ++++++++++++--------------- 7 files changed, 62 insertions(+), 29 deletions(-) diff --git a/kernel/arch/x86_64/IDT.cpp b/kernel/arch/x86_64/IDT.cpp index 76a9f533..37c2f7b7 100644 --- a/kernel/arch/x86_64/IDT.cpp +++ b/kernel/arch/x86_64/IDT.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -135,7 +136,7 @@ namespace IDT "Unkown Exception 0x1F", }; - extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs) + extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, Kernel::InterruptStack& interrupt_stack, const Registers* regs) { pid_t tid = Kernel::Scheduler::current_tid(); pid_t pid = tid ? Kernel::Process::current().pid() : 0; @@ -154,6 +155,12 @@ namespace IDT regs->cr0, regs->cr2, regs->cr3, regs->cr4 ); + if (tid) + { + Kernel::Thread::current().set_return_rsp(interrupt_stack.rsp); + Kernel::Thread::current().set_return_rip(interrupt_stack.rip); + } + if (tid && Kernel::Thread::current().is_userspace() && !Kernel::Thread::current().is_in_syscall()) { auto message = BAN::String::formatted("{}, aborting\n", isr_exceptions[isr]); @@ -167,8 +174,14 @@ namespace IDT } } - extern "C" void cpp_irq_handler(uint64_t irq) + extern "C" void cpp_irq_handler(uint64_t irq, Kernel::InterruptStack& interrupt_stack) { + if (Kernel::Scheduler::current_tid()) + { + Kernel::Thread::current().set_return_rsp(interrupt_stack.rsp); + Kernel::Thread::current().set_return_rip(interrupt_stack.rip); + } + if (s_irq_handlers[irq]) s_irq_handlers[irq](); else diff --git a/kernel/arch/x86_64/interrupts.S b/kernel/arch/x86_64/interrupts.S index eacf910a..e0634861 100644 --- a/kernel/arch/x86_64/interrupts.S +++ b/kernel/arch/x86_64/interrupts.S @@ -64,7 +64,11 @@ isr_stub: movq 176(%rsp), %rdi movq 184(%rsp), %rsi + movq %rsp, %rdx + addq $192, %rdx + + movq %rsp, %rcx call cpp_isr_handler addq $56, %rsp @@ -75,6 +79,8 @@ isr_stub: irq_stub: pushaq movq 0x78(%rsp), %rdi # irq number + movq %rsp, %rsi + addq $136, %rsi call cpp_irq_handler popaq addq $16, %rsp diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 1f2a629c..d4e46ae0 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -101,8 +101,8 @@ namespace Kernel BAN::ErrorOr sys_free(void*); BAN::ErrorOr sys_signal(int, void (*)(int)); - BAN::ErrorOr sys_kill(pid_t pid, int signal, uintptr_t& return_rsp, uintptr_t& return_rip); - BAN::ErrorOr sys_raise(int signal, uintptr_t& return_rsp, uintptr_t& return_rip); + BAN::ErrorOr sys_raise(int signal); + static BAN::ErrorOr sys_kill(pid_t pid, int signal); BAN::ErrorOr sys_termid(char*) const; diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index 35b5ae87..8c76f60b 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -40,7 +40,11 @@ namespace Kernel bool has_signal_to_execute() const; void set_signal_done(int signal); void handle_next_signal(); - void handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip); + + void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; } + void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; } + uintptr_t& return_rsp() { ASSERT(m_return_rsp); return *m_return_rsp; } + uintptr_t& return_rip() { ASSERT(m_return_rip); return *m_return_rip; } pid_t tid() const { return m_tid; } @@ -90,6 +94,9 @@ namespace Kernel bool m_in_syscall { false }; bool m_is_userspace { false }; + uintptr_t* m_return_rsp { nullptr }; + uintptr_t* m_return_rip { nullptr }; + BAN::CircularQueue m_signal_queue; uint64_t m_signal_mask { 0 }; bool m_handling_signal { false }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index d91fff62..494b9e3b 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -806,18 +806,19 @@ namespace Kernel return 0; } - BAN::ErrorOr Process::sys_kill(pid_t pid, int signal, uintptr_t& return_rsp, uintptr_t& return_rip) + BAN::ErrorOr Process::sys_kill(pid_t pid, int signal) { if (pid <= 0) return BAN::Error::from_errno(ENOTSUP); if (signal != 0 && (signal < _SIGMIN || signal > _SIGMAX)) return BAN::Error::from_errno(EINVAL); - if (pid == this->pid()) - return sys_raise(signal, return_rsp, return_rip); - + if (pid == Process::current().pid()) + return Process::current().sys_raise(signal); + LockGuard process_guard(s_process_lock); CriticalScope _; + for (auto* process : s_processes) { if (process->pid() == pid) @@ -831,17 +832,24 @@ namespace Kernel return BAN::Error::from_errno(ESRCH); } - BAN::ErrorOr Process::sys_raise(int signal, uintptr_t& return_rsp, uintptr_t& return_rip) + BAN::ErrorOr Process::sys_raise(int signal) { if (signal < _SIGMIN || signal > _SIGMAX) return BAN::Error::from_errno(EINVAL); ASSERT(m_threads.size() == 1); CriticalScope _; - Thread::current().m_signal_queue.push(signal); - Thread::current().handle_signal(signal, return_rsp, return_rip); + Thread& current = Thread::current(); + current.m_signal_queue.push(signal); + current.handle_next_signal(); return 0; } + pid_t Process::foreground_pid() + { + ASSERT(s_foreground_pid); + return s_foreground_pid; + } + BAN::ErrorOr Process::sys_setuid(uid_t uid) { if (uid < 0 || uid >= 1'000'000'000) diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 913986c6..0b18cb34 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -21,6 +21,8 @@ namespace Kernel extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack) { Thread::current().set_in_syscall(true); + Thread::current().set_return_rsp(interrupt_stack.rsp); + Thread::current().set_return_rip(interrupt_stack.rip); if (syscall == SYS_SIGNAL_DONE) { @@ -147,10 +149,10 @@ namespace Kernel ret = Process::current().sys_dup2((int)arg1, (int)arg2); break; case SYS_RAISE: - ret = Process::current().sys_raise((int)arg1, interrupt_stack.rsp, interrupt_stack.rip); + ret = Process::current().sys_raise((int)arg1); break; case SYS_KILL: - ret = Process::current().sys_kill((pid_t)arg1, (int)arg2, interrupt_stack.rsp, interrupt_stack.rip); + ret = Process::current().sys_kill((pid_t)arg1, (int)arg2); break; case SYS_SIGNAL: ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 47c1430b..70aadbc2 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -7,7 +7,6 @@ #include #include - namespace Kernel { @@ -167,16 +166,14 @@ namespace Kernel { ASSERT(!interrupts_enabled()); ASSERT(!m_signal_queue.empty()); - handle_signal(m_signal_queue.front(), m_rsp, m_rip); - } - - void Thread::handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip) - { - ASSERT(!interrupts_enabled()); - ASSERT(signal >= _SIGMIN && signal <= _SIGMAX); ASSERT(&Thread::current() == this); - ASSERT(!m_signal_queue.empty()); - ASSERT(m_signal_queue.front() == signal); + ASSERT(is_userspace()); + + int signal = m_signal_queue.front(); + ASSERT(signal >= _SIGMIN && signal <= _SIGMAX); + + uintptr_t& return_rsp = this->return_rsp(); + uintptr_t& return_rip = this->return_rip(); vaddr_t signal_handler = process().m_signal_handlers[signal]; @@ -212,8 +209,11 @@ namespace Kernel case SIGTRAP: case SIGXCPU: case SIGXFSZ: - // TODO: additional actions - // fall through + { + auto message = BAN::String::formatted("killed by signal {}\n", signal); + (void)process().tty().write(0, message.data(), message.size()); + } + // fall through // Abnormal termination of the process case SIGALRM: @@ -228,9 +228,6 @@ namespace Kernel case SIGPROF: case SIGVTALRM: { - auto message = BAN::String::formatted("killed by signal {}\n", signal); - (void)process().tty().write(0, message.data(), message.size()); - ENABLE_INTERRUPTS(); process().exit(128 + signal); ASSERT_NOT_REACHED();