PatchworkOS
Loading...
Searching...
No Matches
syscalls.c
Go to the documentation of this file.
2
3#include <kernel/cpu/gdt.h>
5#include <kernel/log/log.h>
6#include <kernel/mem/vmm.h>
9
10#include <kernel/defs.h>
11
12#include <assert.h>
13#include <errno.h>
14#include <stdlib.h>
15
16int syscall_descriptor_cmp(const void* a, const void* b)
17{
18 const syscall_descriptor_t* sysA = (const syscall_descriptor_t*)a;
19 const syscall_descriptor_t* sysB = (const syscall_descriptor_t*)b;
20 return sysA->number - sysB->number;
21}
22
24{
25 // Syscalls are not inserted into the table by the linker in the correct order so we sort them.
26 const uint64_t syscallsInTable =
28 assert(syscallsInTable == SYS_TOTAL_AMOUNT);
29
30 LOG_INFO("sorting syscall table, total system calls %d\n", SYS_TOTAL_AMOUNT);
32
33 for (uint64_t i = 0; i < syscallsInTable; i++)
34 {
35 assert(_syscallTableStart[i].number == i);
36 }
37}
38
49
51{
52 ctx->kernelRsp = kernelStack->top;
53 ctx->userRsp = 0;
54}
55
61
63{
64 if (number > SYS_TOTAL_AMOUNT)
65 {
66 return NULL;
67 }
68
69 return &_syscallTableStart[number];
70}
71
73 uint64_t number)
74{
75 asm volatile("sti");
76
77 const syscall_descriptor_t* desc = syscall_get_descriptor(number);
78 if (desc == NULL)
79 {
80 LOG_DEBUG("Unknown syscall %u\n", number);
81 errno = ENOSYS;
82 return ERR;
83 }
84
85 // This is safe for any input type and any number of arguments up to 6 as they will simply be ignored.
87 uint64_t result = handler(rdi, rsi, rdx, rcx, r8, r9);
88
89 // Interrupts will be renabled when the sysret instruction executes, this means that if there is a pending note and
90 // we invoke an interrupt the actual interrupt handler will not run until we return to user space.
91 asm volatile("cli");
92 if (note_queue_length(&sched_thread_unsafe()->notes) > 0)
93 {
95 }
96
97 return result;
98}
#define assert(expression)
Definition assert.h:29
@ GDT_KERNEL_CODE
Kernel code segment selector.
Definition gdt.h:39
@ GDT_USER_CODE
User code segment selector.
Definition gdt.h:42
@ GDT_RING3
Definition gdt.h:26
@ INTERRUPT_NOTE
Nofify that a note is available.
Definition interrupt.h:136
syscall_descriptor_t _syscallTableEnd[]
Linker defined end of the syscall table.
void syscall_table_init(void)
Initialize the syscall table.
Definition syscalls.c:23
syscall_descriptor_t _syscallTableStart[]
Linker defined start of the syscall table.
void syscalls_cpu_init(void)
Initalize syscalls on the current CPU.
Definition syscalls.c:39
#define SYS_TOTAL_AMOUNT
Definition syscalls.h:56
void syscall_ctx_init(syscall_ctx_t *ctx, stack_pointer_t *kernelStack)
Initialize a per-thread syscall context.
Definition syscalls.c:50
void syscall_ctx_load(syscall_ctx_t *ctx)
Load a syscall context into the CPU.
Definition syscalls.c:56
void syscall_entry(void)
Assembly entry point for syscalls.
uint64_t syscall_handler(uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, uint64_t number)
C syscall handler.
Definition syscalls.c:72
lapic_id_t lapic_self_id(void)
Get the lapic id of the current cpu.
Definition apic.c:171
void lapic_send_ipi(lapic_id_t id, interrupt_t vector)
Send an Inter-Processor Interrupt (IPI) to a local apic.
Definition apic.c:225
uint64_t note_queue_length(note_queue_t *queue)
Get the length of a note queue.
Definition note.c:31
#define LOG_INFO(format,...)
Definition log.h:87
#define LOG_DEBUG(format,...)
Definition log.h:81
thread_t * sched_thread_unsafe(void)
Retrieves the currently running thread without disabling interrupts.
Definition sched.c:175
#define ENOSYS
Function not implemented.
Definition errno.h:222
#define errno
Error number variable.
Definition errno.h:27
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:32
#define RFLAGS_NESTED_TASK
Definition regs.h:36
static void msr_write(uint32_t msr, uint64_t value)
Definition regs.h:71
#define MSR_EFER
Definition regs.h:14
#define RFLAGS_DIRECTION
Definition regs.h:33
#define EFER_SYSCALL_ENABLE
Definition regs.h:21
static uint64_t msr_read(uint32_t msr)
Definition regs.h:63
#define RFLAGS_TRAP
Definition regs.h:31
#define MSR_STAR
Definition regs.h:15
#define RFLAGS_IOPL
Definition regs.h:35
#define MSR_SYSCALL_FLAG_MASK
Definition regs.h:17
#define MSR_LSTAR
Definition regs.h:16
#define MSR_GS_BASE
Definition regs.h:18
#define MSR_KERNEL_GS_BASE
Definition regs.h:19
#define RFLAGS_AUX_CARRY
Definition regs.h:27
__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
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 syscalls.h:63
uintptr_t userRsp
Definition syscalls.h:65
uintptr_t kernelRsp
Definition syscalls.h:64
A syscall descriptor.
Definition syscalls.h:75
int syscall_descriptor_cmp(const void *a, const void *b)
Definition syscalls.c:16
const syscall_descriptor_t * syscall_get_descriptor(uint64_t number)
Definition syscalls.c:62