Kernel/LibC: Add bareboness signals

You can now call raise() to raise a signal. Signal handlers are
not yet supported, but the handling works :)
This commit is contained in:
Bananymous 2023-07-21 15:45:02 +03:00
parent faf4220b38
commit dcd4d0daeb
14 changed files with 126 additions and 3 deletions

View File

@ -75,6 +75,7 @@ if("${BANAN_ARCH}" STREQUAL "x86_64")
arch/x86_64/IDT.cpp arch/x86_64/IDT.cpp
arch/x86_64/interrupts.S arch/x86_64/interrupts.S
arch/x86_64/PageTable.cpp arch/x86_64/PageTable.cpp
arch/x86_64/Signal.S
arch/x86_64/Thread.S arch/x86_64/Thread.S
) )
elseif("${BANAN_ARCH}" STREQUAL "i386") elseif("${BANAN_ARCH}" STREQUAL "i386")

View File

@ -11,6 +11,9 @@ extern uint8_t g_kernel_end[];
extern uint8_t g_kernel_execute_start[]; extern uint8_t g_kernel_execute_start[];
extern uint8_t g_kernel_execute_end[]; extern uint8_t g_kernel_execute_end[];
extern uint8_t g_userspace_start[];
extern uint8_t g_userspace_end[];
namespace Kernel namespace Kernel
{ {
@ -120,6 +123,14 @@ namespace Kernel
g_kernel_execute_end - g_kernel_execute_start, g_kernel_execute_end - g_kernel_execute_start,
Flags::Execute | Flags::Present Flags::Execute | Flags::Present
); );
// Map userspace memory
map_range_at(
V2P(g_userspace_start),
(vaddr_t)g_userspace_start,
g_userspace_end - g_userspace_start,
Flags::Execute | Flags::UserSupervisor | Flags::Present
);
} }
BAN::ErrorOr<PageTable*> PageTable::create_userspace() BAN::ErrorOr<PageTable*> PageTable::create_userspace()

View File

@ -0,0 +1,51 @@
.section .userspace, "aw"
.global signal_trampoline
signal_trampoline:
pushq %rax
pushq %rbx
pushq %rcx
pushq %rdx
pushq %rbp
pushq %rdi
pushq %rsi
pushq %r8
pushq %r9
pushq %r10
pushq %r11
pushq %r12
pushq %r13
pushq %r14
pushq %r15
xchgw %bx, %bx
movq 128(%rsp), %rdi
movq 120(%rsp), %rax
call *%rax
popq %r15
popq %r14
popq %r13
popq %r12
popq %r11
popq %r10
popq %r9
popq %r8
popq %rsi
popq %rdi
popq %rbp
popq %rdx
popq %rcx
popq %rbx
popq %rax
addq $16, %rsp
ret
.global test_signal
test_signal:
movq $99, %rax
int $0x80
ret

View File

@ -11,7 +11,13 @@ SECTIONS
{ {
g_kernel_execute_start = .; g_kernel_execute_start = .;
*(.multiboot) *(.multiboot)
*(.text) *(.text.*)
}
.userspace ALIGN(4K) : AT(ADDR(.userspace) - KERNEL_OFFSET)
{
g_userspace_start = .;
*(.userspace)
g_userspace_end = .;
} }
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) .rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
{ {

View File

@ -100,6 +100,10 @@ namespace Kernel
BAN::ErrorOr<long> sys_alloc(size_t); BAN::ErrorOr<long> sys_alloc(size_t);
BAN::ErrorOr<long> sys_free(void*); BAN::ErrorOr<long> sys_free(void*);
BAN::ErrorOr<long> sys_signal(int, void (*)(int));
BAN::ErrorOr<long> sys_kill(pid_t pid, int signal);
BAN::ErrorOr<long> sys_raise(int signal, uintptr_t& return_rsp, uintptr_t& return_rip);
BAN::ErrorOr<long> sys_termid(char*) const; BAN::ErrorOr<long> sys_termid(char*) const;
BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*) const; BAN::ErrorOr<long> sys_clock_gettime(clockid_t, timespec*) const;

View File

@ -14,6 +14,9 @@
#include <stdio.h> #include <stdio.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
extern "C" void signal_trampoline();
extern "C" void test_signal();
namespace Kernel namespace Kernel
{ {
@ -788,6 +791,27 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_raise(int signal, uintptr_t& return_rsp, uintptr_t& return_rip)
{
if (signal < _SIGMIN || signal > _SIGMAX)
return BAN::Error::from_errno(EINVAL);
ASSERT(&Process::current() == this);
LockGuard lock_guard(m_lock);
asm volatile("cli");
uintptr_t* return_rsp_ptr = (uintptr_t*)return_rsp;
*--return_rsp_ptr = return_rip;
*--return_rsp_ptr = signal;
*--return_rsp_ptr = (uintptr_t)test_signal;
return_rsp = (uintptr_t)return_rsp_ptr;
return_rip = (uintptr_t)signal_trampoline;
return 0;
}
BAN::ErrorOr<long> Process::sys_setuid(uid_t uid) BAN::ErrorOr<long> Process::sys_setuid(uid_t uid)
{ {
if (uid < 0 || uid >= 1'000'000'000) if (uid < 0 || uid >= 1'000'000'000)

View File

@ -140,6 +140,9 @@ namespace Kernel
case SYS_DUP2: case SYS_DUP2:
ret = Process::current().sys_dup2((int)arg1, (int)arg2); ret = Process::current().sys_dup2((int)arg1, (int)arg2);
break; break;
case SYS_RAISE:
ret = Process::current().sys_raise((int)arg1, interrupt_stack.rsp, interrupt_stack.rip);
break;
default: default:
dwarnln("Unknown syscall {}", syscall); dwarnln("Unknown syscall {}", syscall);
break; break;

View File

@ -98,8 +98,8 @@ namespace BAN::Formatter
} }
extern "C" uintptr_t g_kernel_start; extern "C" uint8_t g_userspace_start[];
extern "C" uintptr_t g_kernel_end; extern "C" uint8_t g_userspace_end[];
static void init2(void*); static void init2(void*);

View File

@ -9,6 +9,7 @@ set(LIBC_SOURCES
fcntl.cpp fcntl.cpp
printf_impl.cpp printf_impl.cpp
pwd.cpp pwd.cpp
signal.cpp
stdio.cpp stdio.cpp
stdlib.cpp stdlib.cpp
string.cpp string.cpp

View File

@ -74,6 +74,9 @@ struct sigevent
#define SIGRTMIN 29 #define SIGRTMIN 29
#define SIGRTMAX (SIGRTMIN+32) #define SIGRTMAX (SIGRTMIN+32)
#define _SIGMIN SIGABRT
#define _SIGMAX SIGRTMAX
#define SIG_BLOCK 1 #define SIG_BLOCK 1
#define SIG_UNBLOCK 2 #define SIG_UNBLOCK 2
#define SIG_SETMASK 3 #define SIG_SETMASK 3

View File

@ -41,6 +41,7 @@ __BEGIN_DECLS
#define SYS_CLOCK_GETTIME 34 #define SYS_CLOCK_GETTIME 34
#define SYS_PIPE 35 #define SYS_PIPE 35
#define SYS_DUP2 36 #define SYS_DUP2 36
#define SYS_RAISE 37
__END_DECLS __END_DECLS

8
libc/signal.cpp Normal file
View File

@ -0,0 +1,8 @@
#include <signal.h>
#include <sys/syscall.h>
#include <unistd.h>
int raise(int sig)
{
return syscall(SYS_RAISE, sig);
}

View File

@ -266,6 +266,12 @@ long syscall(long syscall, ...)
ret = Kernel::syscall(SYS_DUP2, fildes, fildes2); ret = Kernel::syscall(SYS_DUP2, fildes, fildes2);
break; break;
} }
case SYS_RAISE:
{
int signal = va_arg(args, int);
ret = Kernel::syscall(SYS_RAISE, signal);
break;
}
default: default:
puts("LibC: Unhandeled syscall"); puts("LibC: Unhandeled syscall");
ret = -ENOSYS; ret = -ENOSYS;

View File

@ -260,6 +260,10 @@ int execute_command(BAN::Vector<BAN::String>& args)
while (*current) while (*current)
printf("%s\n", *current++); printf("%s\n", *current++);
} }
else if (args.front() == "raise"sv)
{
raise(SIGSEGV);
}
else if (args.front() == "cd"sv) else if (args.front() == "cd"sv)
{ {
if (args.size() > 2) if (args.size() > 2)