PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
syscall.c
Go to the documentation of this file.
3
4#include <kernel/cpu/cpu.h>
5#include <kernel/cpu/gdt.h>
6#include <kernel/log/log.h>
7#include <kernel/mem/vmm.h>
10
11#include <sys/defs.h>
12
13#include <assert.h>
14#include <errno.h>
15#include <stdlib.h>
16
27
28void syscall_ctx_init(syscall_ctx_t* ctx, const stack_pointer_t* syscallStack)
29{
30 ctx->syscallRsp = syscallStack->top;
31 ctx->userRsp = 0;
32 ctx->frame = NULL;
33 ctx->flags = SYSCALL_NORMAL;
34}
35
37{
38 SELF->syscallRsp = ctx->syscallRsp;
39 SELF->userRsp = ctx->userRsp;
40}
41
42static int syscall_descriptor_cmp(const void* a, const void* b)
43{
44 const syscall_descriptor_t* sysA = (const syscall_descriptor_t*)a;
45 const syscall_descriptor_t* sysB = (const syscall_descriptor_t*)b;
46 return (int32_t)sysA->number - (int32_t)sysB->number;
47}
48
50{
51 // Syscalls are not inserted into the table by the linker in the correct order so we sort them.
52 const uint64_t syscallsInTable =
54 assert(syscallsInTable == SYS_TOTAL_AMOUNT);
55
56 LOG_INFO("sorting syscall table, total system calls %d\n", SYS_TOTAL_AMOUNT);
58
59 for (uint64_t i = 0; i < syscallsInTable; i++)
60 {
61 assert(_syscall_table_start[i].number == i);
62 }
63}
64
66{
67 if (number > SYS_TOTAL_AMOUNT)
68 {
69 return NULL;
70 }
71
72 return &_syscall_table_start[number];
73}
74
76{
78 if (desc == NULL)
79 {
80 LOG_DEBUG("Unknown syscall %u\n", frame->rax);
81 errno = ENOSYS;
82 frame->rax = ERR;
83 return;
84 }
85
86 thread_t* thread = thread_current();
88
89 thread->syscall.frame = frame;
91
92 // This is safe for any input type and any number of arguments up to 6 as they will simply be ignored.
93 uint64_t result = desc->handler(frame->rdi, frame->rsi, frame->rdx, frame->r10, frame->r8, frame->r9);
95 {
96 frame->rax = result;
97 }
98
100
102 ASM("cli" :: : "memory");
104 {
105 frame->vector = VECTOR_FAKE;
106 interrupt_fake(frame);
107 }
108}
#define assert(expression)
Definition assert.h:29
#define GDT_KERNEL_CODE
Kernel code segment selector.
Definition gdt.h:29
#define GDT_RING3
User ring.
Definition gdt.h:26
#define GDT_USER_CODE
User code segment selector.
Definition gdt.h:32
_NORETURN void interrupt_fake(interrupt_frame_t *frame)
Enter a fake interrupt context as if an interrupt had occurred at the given frame.
@ VECTOR_FAKE
Used to implement interrupt_fake().
Definition interrupt.h:178
#define SELF
Macro to access data in the current cpu.
Definition percpu.h:85
#define PERCPU_DEFINE_CTOR(type, name)
Macro to define a percpu variable with a constructor.
Definition percpu.h:130
void syscall_ctx_init(syscall_ctx_t *ctx, const stack_pointer_t *syscallStack)
Initialize a syscall context.
Definition syscall.c:28
void syscall_table_init(void)
Sort the syscall table and verify that all syscalls are present.
Definition syscall.c:49
syscall_descriptor_t _syscall_table_start[]
Linker defined start of the syscall table.
syscall_descriptor_t _syscall_table_end[]
Linker defined end of the syscall table.
void syscall_handler(interrupt_frame_t *frame)
Main C syscall handler.
Definition syscall.c:75
void syscall_ctx_load(syscall_ctx_t *ctx)
Load the syscall context into the MSR_KERNEL_GS_BASE MSR.
Definition syscall.c:36
void syscall_entry(void)
Assembly entry point for syscalls.
@ SYS_TOTAL_AMOUNT
Definition syscall.h:108
@ SYSCALL_FORCE_FAKE_INTERRUPT
Definition syscall.h:125
@ SYSCALL_NORMAL
Definition syscall.h:117
void perf_syscall_end(void)
Called at the end of a syscall to update process performance data.
Definition perf.c:248
void perf_syscall_begin(void)
Called at the beginning of a syscall to update process performance data.
Definition perf.c:226
#define LOG_INFO(format,...)
Definition log.h:91
#define LOG_DEBUG(format,...)
Definition log.h:85
bool thread_is_note_pending(thread_t *thread)
Check if a thread has a note pending.
Definition thread.c:171
static thread_t * thread_current(void)
Retrieves the currently running thread.
Definition thread.h:126
#define ENOSYS
Function not implemented.
Definition errno.h:222
#define errno
Error number variable.
Definition errno.h:27
#define ASM(...)
Inline assembly macro.
Definition defs.h:160
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:34
#define RFLAGS_NESTED_TASK
Definition regs.h:38
static void msr_write(uint32_t msr, uint64_t value)
Definition regs.h:73
#define MSR_EFER
Definition regs.h:15
static uint64_t rflags_read(void)
Definition regs.h:80
#define RFLAGS_DIRECTION
Definition regs.h:35
#define EFER_SYSCALL_ENABLE
Definition regs.h:23
static uint64_t msr_read(uint32_t msr)
Definition regs.h:65
#define RFLAGS_TRAP
Definition regs.h:33
#define MSR_STAR
Definition regs.h:16
#define RFLAGS_IOPL
Definition regs.h:37
#define MSR_SYSCALL_FLAG_MASK
Definition regs.h:18
#define MSR_LSTAR
Definition regs.h:17
#define RFLAGS_AUX_CARRY
Definition regs.h:29
__INT32_TYPE__ int32_t
Definition stdint.h:14
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Definition qsort.c:47
Trap Frame Structure.
Definition interrupt.h:195
Structure to define a stack in memory.
uintptr_t top
The top of the stack, this address is not inclusive.
Per thread syscall context.
Definition syscall.h:133
uintptr_t userRsp
Used to avoid clobbering registers when switching stacks.
Definition syscall.h:135
interrupt_frame_t * frame
If a fake interrupt is generated, this is the interrupt frame to return to.
Definition syscall.h:136
uintptr_t syscallRsp
The stack pointer to use when handling syscalls.
Definition syscall.h:134
syscall_flags_t flags
Flags for the current syscall.
Definition syscall.h:137
A syscall descriptor.
Definition syscall.h:147
uint64_t(* handler)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)
Definition syscall.h:149
Thread of execution structure.
Definition thread.h:61
syscall_ctx_t syscall
Definition thread.h:79
const syscall_descriptor_t * syscall_get_descriptor(uint64_t number)
Definition syscall.c:65
static int syscall_descriptor_cmp(const void *a, const void *b)
Definition syscall.c:42