From 8375870af64370ca4a6d6f972e3dcaac73e2c54b Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Tue, 2 Apr 2019 23:14:52 -0700 Subject: [PATCH] Improve syscall definitions - Allow constant id specification - Define function signature in SYSCALL macro - Move implementation into src/kernel/syscalls/*.cpp --- modules.yaml | 7 +++ src/drivers/nulldrv/main.cpp | 2 + src/drivers/nulldrv/main.s | 24 ++++++-- src/kernel/syscall.cpp | 100 ++++++++++---------------------- src/kernel/syscall.h | 14 ++++- src/kernel/syscall.s | 14 ++--- src/kernel/syscalls.inc | 18 +++--- src/kernel/syscalls/exit.cpp | 17 ++++++ src/kernel/syscalls/getpid.cpp | 14 +++++ src/kernel/syscalls/message.cpp | 14 +++++ src/kernel/syscalls/noop.cpp | 14 +++++ src/kernel/syscalls/pause.cpp | 15 +++++ src/kernel/syscalls/sleep.cpp | 17 ++++++ 13 files changed, 173 insertions(+), 97 deletions(-) create mode 100644 src/kernel/syscalls/exit.cpp create mode 100644 src/kernel/syscalls/getpid.cpp create mode 100644 src/kernel/syscalls/message.cpp create mode 100644 src/kernel/syscalls/noop.cpp create mode 100644 src/kernel/syscalls/pause.cpp create mode 100644 src/kernel/syscalls/sleep.cpp diff --git a/modules.yaml b/modules.yaml index cdae6ac..8a65431 100644 --- a/modules.yaml +++ b/modules.yaml @@ -41,6 +41,13 @@ modules: - src/kernel/serial.cpp - src/kernel/syscall.cpp - src/kernel/syscall.s + - src/kernel/syscalls/exit.cpp + - src/kernel/syscalls/fork.cpp + - src/kernel/syscalls/getpid.cpp + - src/kernel/syscalls/message.cpp + - src/kernel/syscalls/noop.cpp + - src/kernel/syscalls/pause.cpp + - src/kernel/syscalls/sleep.cpp - src/kernel/task.s - src/kernel/crtn.s diff --git a/src/drivers/nulldrv/main.cpp b/src/drivers/nulldrv/main.cpp index dc75219..6e9b523 100644 --- a/src/drivers/nulldrv/main.cpp +++ b/src/drivers/nulldrv/main.cpp @@ -6,6 +6,7 @@ extern "C" { int32_t fork(); void sleep(uint64_t til); void debug(); + void message(const char *msg); int main(int, const char **); } @@ -15,6 +16,7 @@ int main(int argc, const char **argv) { int32_t pid = getpid(); + message("hello from nulldrv!"); //int32_t child = fork(); //debug(); for (int i = 1; i < 5; ++i) diff --git a/src/drivers/nulldrv/main.s b/src/drivers/nulldrv/main.s index 8089ae5..1835de2 100644 --- a/src/drivers/nulldrv/main.s +++ b/src/drivers/nulldrv/main.s @@ -11,8 +11,8 @@ getpid: push rbp mov rbp, rsp - mov rax, 3 ; getpid syscall - syscall ; pid is now already in rax, so just return + mov rax, 0x02 ; getpid syscall + syscall ; pid is now already in rax, so just return pop rbp ret @@ -22,7 +22,7 @@ debug: push rbp mov rbp, rsp - mov rax, 0 ; debug syscall + mov rax, 0x00 ; debug syscall syscall pop rbp @@ -33,7 +33,7 @@ sleep: push rbp mov rbp, rsp - mov rax, 6 ; sleep syscall + mov rax, 0x21 ; sleep syscall syscall pop rbp @@ -44,14 +44,26 @@ fork: push rbp mov rbp, rsp - mov rax, 0 - + mov rax, 0x00 syscall ; pid left in rax pop rbp ret +global message +message: + push rbp + mov rbp, rsp + + ; message should already be in rdi + mov rax, 0x10 + syscall + + pop rbp + ret + + global _start _start: xor rbp, rbp ; Sentinel rbp diff --git a/src/kernel/syscall.cpp b/src/kernel/syscall.cpp index 0e238f8..15ddc25 100644 --- a/src/kernel/syscall.cpp +++ b/src/kernel/syscall.cpp @@ -8,89 +8,42 @@ #include "syscall.h" extern "C" { - void _halt(); + void syscall_invalid(uint64_t call); void syscall_handler_prelude(); } namespace syscalls { -void -noop() -{ - auto &s = scheduler::get(); - auto *p = s.current(); - log::debug(logs::syscall, "Process %d called noop syscall.", p->pid); -} - -void -exit(int64_t status) -{ - auto &s = scheduler::get(); - auto *p = s.current(); - log::debug(logs::syscall, "Process %d exiting with code %d", p->pid, status); - - p->exit(status); - s.schedule(); -} - -pid_t -getpid() -{ - auto &s = scheduler::get(); - auto *p = s.current(); - return p->pid; -} - pid_t fork() { return 0; } -void -message(const char *message) -{ - auto &s = scheduler::get(); - auto *p = s.current(); - log::info(logs::syscall, "Message[%d]: %s", p->pid, message); -} - -void -pause() -{ - auto &s = scheduler::get(); - auto *p = s.current(); - p->wait_on_signal(-1ull); - s.schedule(); -} - -void -sleep(uint64_t til) -{ - auto &s = scheduler::get(); - auto *p = s.current(); - log::debug(logs::syscall, "Process %d sleeping until %d", p->pid, til); - - p->wait_on_time(til); - s.schedule(); -} - void send() {} void receive() {} } // namespace syscalls -struct syscall_handler_info -{ - unsigned nargs; - const char *name; -}; - -uintptr_t syscall_registry[static_cast(syscall::COUNT)]; -syscall_handler_info syscall_info_registry[static_cast(syscall::COUNT)]; +uintptr_t syscall_registry[static_cast(syscall::MAX)]; +const char * syscall_names[static_cast(syscall::MAX)]; void syscall_invalid(uint64_t call) { console *cons = console::get(); cons->set_color(9); - cons->printf("\nReceived unknown syscall: %d\n", call); + cons->printf("\nReceived unknown syscall: %02x\n", call); + + const unsigned num_calls = + static_cast(syscall::MAX); + + cons->printf(" Known syscalls:\n"); + cons->printf(" invalid %016lx\n", syscall_invalid); + + for (unsigned i = 0; i < num_calls; ++i) { + const char *name = syscall_names[i]; + uintptr_t handler = syscall_registry[i]; + if (name) + cons->printf(" %02x %10s %016lx\n", i, name, handler); + } + cons->set_color(); _halt(); } @@ -190,11 +143,18 @@ syscall_enable() // IA32_FMASK - FLAGS mask inside syscall wrmsr(msr::ia32_fmask, 0x200); -#define SYSCALL(name, nargs) \ - syscall_registry[static_cast(syscall::name)] = \ - reinterpret_cast(syscalls::name); \ - syscall_info_registry[static_cast(syscall::name)] = { \ - nargs, #name }; + static constexpr unsigned num_calls = + static_cast(syscall::MAX); + + for (unsigned i = 0; i < num_calls; ++i) { + syscall_registry[i] = reinterpret_cast(syscall_invalid); + syscall_names[i] = nullptr; + } + +#define SYSCALL(id, name, result, ...) \ + syscall_registry[id] = reinterpret_cast(syscalls::name); \ + syscall_names[id] = #name; \ + static_assert( id <= num_calls, "Syscall " #name " has id > syscall::MAX" ); #include "syscalls.inc" #undef SYSCALL } diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h index 0c3b723..d7a751b 100644 --- a/src/kernel/syscall.h +++ b/src/kernel/syscall.h @@ -6,12 +6,20 @@ struct cpu_state; enum class syscall : uint64_t { -#define SYSCALL(name, nargs) name , +#define SYSCALL(id, name, result, ...) name = id, #include "syscalls.inc" #undef SYSCALL - COUNT + // Maximum syscall id. If you change this, also change + // MAX_SYSCALLS in syscall.s + MAX = 64 }; void syscall_enable(); -extern "C" void syscall_invalid(uint64_t call); + +namespace syscalls +{ +#define SYSCALL(id, name, result, ...) result name (__VA_ARGS__); +#include "syscalls.inc" +#undef SYSCALL +} diff --git a/src/kernel/syscall.s b/src/kernel/syscall.s index a1b43aa..81871d0 100644 --- a/src/kernel/syscall.s +++ b/src/kernel/syscall.s @@ -1,13 +1,9 @@ %include "push_all.inc" %include "tasking.inc" -%define SYSCALL(name, nargs) resb 1 - -struc SYSCALLS -%include "syscalls.inc" -.count: -endstruc - +; Make sure to keep MAX_SYSCALLS in sync with +; syscall::MAX in syscall.h +MAX_SYSCALLS equ 64 extern __counter_syscall_enter extern __counter_syscall_sysret @@ -28,8 +24,8 @@ syscall_handler_prelude: inc qword [rel __counter_syscall_enter] - cmp rax, SYSCALLS.count - jl .ok_syscall + cmp rax, MAX_SYSCALLS + jle .ok_syscall mov rdi, rax call syscall_invalid diff --git a/src/kernel/syscalls.inc b/src/kernel/syscalls.inc index f705fdc..15f9515 100644 --- a/src/kernel/syscalls.inc +++ b/src/kernel/syscalls.inc @@ -1,12 +1,12 @@ -SYSCALL(noop, 0) -SYSCALL(exit, 1) -SYSCALL(getpid, 0) -SYSCALL(fork, 0) +SYSCALL(0x00, noop, void) +SYSCALL(0x01, exit, void, int64_t) +SYSCALL(0x02, getpid, pid_t) +SYSCALL(0x03, fork, pid_t) -SYSCALL(message, 1) +SYSCALL(0x10, message, void, const char *) -SYSCALL(pause, 0) -SYSCALL(sleep, 1) +SYSCALL(0x20, pause, void) +SYSCALL(0x21, sleep, void, uint64_t) -SYSCALL(send, 2) -SYSCALL(receive, 2) +SYSCALL(0x30, send, void) +SYSCALL(0x31, receive, void) diff --git a/src/kernel/syscalls/exit.cpp b/src/kernel/syscalls/exit.cpp new file mode 100644 index 0000000..5f45733 --- /dev/null +++ b/src/kernel/syscalls/exit.cpp @@ -0,0 +1,17 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +void +exit(int64_t status) +{ + auto &s = scheduler::get(); + auto *p = s.current(); + log::debug(logs::syscall, "Process %d exiting with code %d", p->pid, status); + + p->exit(status); + s.schedule(); +} + +} // namespace syscalls diff --git a/src/kernel/syscalls/getpid.cpp b/src/kernel/syscalls/getpid.cpp new file mode 100644 index 0000000..0424a1f --- /dev/null +++ b/src/kernel/syscalls/getpid.cpp @@ -0,0 +1,14 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +pid_t +getpid() +{ + auto &s = scheduler::get(); + auto *p = s.current(); + return p->pid; +} + +} // namespace syscalls diff --git a/src/kernel/syscalls/message.cpp b/src/kernel/syscalls/message.cpp new file mode 100644 index 0000000..11f79d3 --- /dev/null +++ b/src/kernel/syscalls/message.cpp @@ -0,0 +1,14 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +void +message(const char *message) +{ + auto &s = scheduler::get(); + auto *p = s.current(); + log::info(logs::syscall, "Message[%d]: %s", p->pid, message); +} + +} // namespace syscalls diff --git a/src/kernel/syscalls/noop.cpp b/src/kernel/syscalls/noop.cpp new file mode 100644 index 0000000..7654693 --- /dev/null +++ b/src/kernel/syscalls/noop.cpp @@ -0,0 +1,14 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +void +noop() +{ + auto &s = scheduler::get(); + auto *p = s.current(); + log::debug(logs::syscall, "Process %d called noop syscall.", p->pid); +} + +} // namespace syscalls diff --git a/src/kernel/syscalls/pause.cpp b/src/kernel/syscalls/pause.cpp new file mode 100644 index 0000000..8c03990 --- /dev/null +++ b/src/kernel/syscalls/pause.cpp @@ -0,0 +1,15 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +void +pause() +{ + auto &s = scheduler::get(); + auto *p = s.current(); + p->wait_on_signal(-1ull); + s.schedule(); +} + +} // namespace syscalls diff --git a/src/kernel/syscalls/sleep.cpp b/src/kernel/syscalls/sleep.cpp new file mode 100644 index 0000000..58ef385 --- /dev/null +++ b/src/kernel/syscalls/sleep.cpp @@ -0,0 +1,17 @@ +#include "log.h" +#include "scheduler.h" + +namespace syscalls { + +void +sleep(uint64_t til) +{ + auto &s = scheduler::get(); + auto *p = s.current(); + log::debug(logs::syscall, "Process %d sleeping until %d", p->pid, til); + + p->wait_on_time(til); + s.schedule(); +} + +} // namespace syscalls