working syscalls!!!!!

This commit is contained in:
2023-10-26 18:18:38 +02:00
parent 9fc44baaff
commit b0cdd10db2
14 changed files with 140 additions and 28 deletions

View File

@@ -10,4 +10,6 @@
#define KERN_STACK_SIZE (1024 * 1024)
extern uint64_t KERN_stack[KERN_STACK_SIZE] __attribute__((aligned(16)));
#define TASK_POINTER 0x10000
#endif//OS1_GLOBALS_H

View File

@@ -16,6 +16,7 @@
#include "mutex.hpp"
#include "rand.h"
#include "syscalls.hpp"
#include "syscalls_interface.h"
#include "task.hpp"
#include "timer.hpp"
#include "tty.hpp"
@@ -191,7 +192,7 @@ void stress_tester() {
void user_task() {
while (true) {
asm("syscall");
putchar('h');
__builtin_ia32_pause();
}
}

View File

@@ -1,7 +1,22 @@
[BITS 64]
extern syscall_impl
section .text
global _syscall_entrypoint:function (_syscall_entrypoint.end - _syscall_entrypoint)
_syscall_entrypoint:
sysret
; TODO: make it synced somehow
mov r11, 0x10016 ; TASK_POINTER->ret_sp_val
mov [r11], rsp
mov r11, 0x10008 ; TASK_POINTER->entry_ksp_val
mov rsp, [r11]
mov r15, rcx
; Do very complicated stuff here
call syscall_impl
mov r11, 0x10016 ; TASK_POINTER->entry_ksp_val
mov rsp, [r11]
mov rcx, r15
o64 sysret
.end:

View File

@@ -3,12 +3,14 @@
//
#include "syscalls.hpp"
#include "syscalls_defs.h"
#include <cstdint>
#include "asserts.hpp"
#include "gdt.hpp"
#include "misc.hpp"
#include "tty.hpp"
struct STAR {
unsigned ret_cs_ss : 16;
@@ -37,4 +39,18 @@ void setup_syscalls() {
wrmsr(0xc0000084, 0);
wrmsr(0xC0000080, rdmsr(0xC0000080) | 0b1);
}
}
uint64_t syscall_putchar(char c) {
all_tty_putchar(c);
return 0;
}
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx) {
switch (id_rdi) {
case SYSCALL_PUTCHAR_ID:
return syscall_putchar(a1_rsi);
default:
return -1;
}
}

View File

@@ -5,8 +5,11 @@
#ifndef OS2_SYSCALLS_HPP
#define OS2_SYSCALLS_HPP
#include <cstdint>
void setup_syscalls();
extern "C" void _syscall_entrypoint();
extern "C" uint64_t syscall_impl(uint64_t id_rdi, uint64_t a1_rsi, uint64_t a2_rdx, uint64_t a3_rcx);
#endif//OS2_SYSCALLS_HPP

View File

@@ -3,9 +3,6 @@
%include "task.inc.asm"
extern switch_task
extern gdt_code
extern gdt_null
extern gdt_data
; FIXME: 75% chance this leaks stack or something
section .text
@@ -14,12 +11,8 @@ _yield_self_kern:
pop rsi ; save the return ip
mov r8, rsp ; save cur sp
mov r10, gdt_null
mov r9, gdt_data
mov r11, gdt_code
sub r9, r10
sub r11, r10
mov r9, ss
mov r11, cs
PUSH r9; Push data segment
push r8 ; current sp

View File

@@ -9,6 +9,7 @@
#include "VMA.hpp"
#include "asserts.hpp"
#include "gdt.hpp"
#include "globals.hpp"
#include "kmem.hpp"
#include "misc.hpp"
#include "mutex.hpp"
@@ -20,7 +21,8 @@
char temp_fxsave[512] __attribute__((aligned(16)));
void sanity_check_frame(struct task_frame *cur_frame) {
assert((((uintptr_t) cur_frame) & 0xFULL) == 0);
// TODO: This makes sense to check when entering, but not when switching
// assert((((uintptr_t) cur_frame) & 0xFULL) == 0);
assert2((void *) cur_frame->ip != NULL, "Sanity check");
assert2((void *) cur_frame->sp != NULL, "Sanity check");
assert2(cur_frame->guard == IDT_GUARD, "IDT Guard wrong!");
@@ -125,7 +127,7 @@ struct Task *new_ktask(void (*fn)(), const char *name) {
return newt;
}
struct Task *new_utask(void (*fn)(), const char *name) {
struct Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
Task *newt = static_cast<Task *>(kmalloc(sizeof(struct Task)));
newt->kstack = static_cast<uint64_t *>(kmalloc(TASK_SS));
newt->name = static_cast<char *>(kmalloc(strlen(name) + 1));
newt->fxsave = static_cast<char *>(kmalloc(512));
@@ -146,7 +148,20 @@ struct Task *new_utask(void (*fn)(), const char *name) {
newt->pid = max_pid.fetch_add(1);
newt->used_time = 0;
void *ustack = newt->vma->mmap_mem_any(TASK_SS, 0, 0);
task_pointer *taskptr = static_cast<task_pointer *>(newt->vma->mmap_mem(reinterpret_cast<void *>(TASK_POINTER), sizeof(task_pointer), 0, PAGE_RW));
assert((uintptr_t) taskptr == TASK_POINTER);
task_pointer *taskptr_real = reinterpret_cast<task_pointer *>(HHDM_P2V(newt->addressSpace->virt2real(taskptr)));
newt->entry_ksp_val = ((((uintptr_t) newt->kstack) + (TASK_SS - 9) - 1) & (~0xFULL));// Ensure 16byte alignment
// It should be aligned before call, therefore it actually should be aligned here
assert((newt->entry_ksp_val & 0xFULL) == 0);
taskptr_real->taskptr = newt;
taskptr_real->entry_ksp_val = &newt->entry_ksp_val;
taskptr_real->ret_sp = 0xFEFE;
void *ustack = newt->vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);
newt->frame.sp = ((((uintptr_t) ustack) + (TASK_SS - 17) - 1) & (~0xFULL)) + 8;// Ensure 16byte alignment
// It should be aligned before call, therefore on function entry it should be misaligned by 8 bytes
@@ -212,9 +227,7 @@ void sleep_self(uint64_t diff) {
void yield_self() {
if (!RunningTask) return;
NO_INT(
if (RunningTask->val->mode == TASKMODE_KERN) {
_yield_self_kern();
})
_yield_self_kern();)
}
static void task_waker() {

View File

@@ -28,6 +28,7 @@ struct AddressSpace;
class VMA;
struct Task {
uint64_t entry_ksp_val;
struct task_frame frame;
uint64_t pid;
std::atomic<uint64_t> used_time;
@@ -41,6 +42,12 @@ struct Task {
enum TaskState state;
};
struct task_pointer {
Task *taskptr;
uint64_t *entry_ksp_val;
uint64_t ret_sp;
} __attribute__((packed));
struct Task *cur_task();
List<Task *>::Node *extract_running_task_node();

View File

@@ -1,5 +1,5 @@
target_include_directories(kernel.elf PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_sources(kernel.elf PRIVATE mutex.cpp cppsupport.cpp Spinlock.cpp LockGuard.cpp rand.cpp VMA.cpp asserts.cpp)
target_sources(kernel.elf PRIVATE mutex.cpp cppsupport.cpp Spinlock.cpp LockGuard.cpp rand.cpp VMA.cpp asserts.cpp syscalls_interface.c)
add_subdirectory(templates)

View File

@@ -38,21 +38,25 @@ void *VMA::mmap_phys(void *v_addr, void *real_addr, size_t length, int flags) {
return v_addr;
}
void *VMA::mmap_mem_any(size_t length, int prot, int flags) {
if ((length & PAGE_SIZE) != 0) {
void *VMA::mmap_mem(void *v_addr, size_t length, int prot, int flags) {
if ((length & (PAGE_SIZE - 1)) != 0) {
length += PAGE_SIZE - 1;
length &= ~PAGE_SIZE;
length &= ~(PAGE_SIZE - 1);
}
assert((length & PAGE_SIZE) == 0);
assert((length & (PAGE_SIZE - 1)) == 0);
uint64_t page_len = length / PAGE_SIZE;
std::optional<ListEntry> found;
{
LockGuard l(regions_lock);
for (auto &n: regions) {
if (n.data.available && n.data.length >= length) {
found = n.data;
if (v_addr) {
found = regions.find((uintptr_t) v_addr)->data;
} else {
for (auto &n: regions) {
if (n.data.available && n.data.length >= length) {
found = n.data;
}
}
}
if (!found) return nullptr;
@@ -65,7 +69,7 @@ void *VMA::mmap_mem_any(size_t length, int prot, int flags) {
void *p = get4k();
{
LockGuard l(space_lock);
space->map(reinterpret_cast<void *>(found->begin + i * PAGE_SIZE), (void *) HHDM_V2P(p), PAGE_RW | PAGE_USER);
space->map(reinterpret_cast<void *>(found->begin + i * PAGE_SIZE), (void *) HHDM_V2P(p), flags);
}
}
return reinterpret_cast<void *>(found->begin);

View File

@@ -22,7 +22,7 @@ public:
/// By linking them to same entries as kernel
void map_kern();
void *mmap_phys(void *v_addr, void *real_addr, size_t length, int flags);
void *mmap_mem_any(size_t length, int prot, int flags);
void *mmap_mem(void *v_addr, size_t length, int prot, int flags);
int munmap(void *addr, size_t length);
private:

View File

@@ -0,0 +1,21 @@
//
// Created by Stepan Usatiuk on 26.10.2023.
//
#ifndef OS2_SYSCALLS_DEFS_H
#define OS2_SYSCALLS_DEFS_H
#ifdef __cplusplus
#include <cstdint>
extern "C" {
#else
#include <stdint.h>
#endif
#define SYSCALL_PUTCHAR_ID 1
#ifdef __cplusplus
}
#endif
#endif//OS2_SYSCALLS_DEFS_H

View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 26.10.2023.
//
#include "syscalls_interface.h"
#include "syscalls_defs.h"
uint64_t putchar(char c) {
uint64_t res;
uint64_t id = SYSCALL_PUTCHAR_ID;
asm("syscall"
: "=r"(res)
: "Di"(id), "Si"(c)
: "memory");
return res;
}

View File

@@ -0,0 +1,21 @@
//
// Created by Stepan Usatiuk on 26.10.2023.
//
#ifndef OS2_SYSCALLS_INTERFACE_H
#define OS2_SYSCALLS_INTERFACE_H
#ifdef __cplusplus
#include <cstdint>
extern "C" {
#else
#include <stdint.h>
#endif
uint64_t putchar(char c);
#ifdef __cplusplus
}
#endif
#endif//OS2_SYSCALLS_INTERFACE_H