working sleep syscall

yes it turns out it was 100% completely broken before
This commit is contained in:
2023-10-26 23:04:23 +02:00
parent b0cdd10db2
commit 9fa74148dd
9 changed files with 38 additions and 10 deletions

View File

@@ -193,7 +193,9 @@ void stress_tester() {
void user_task() {
while (true) {
putchar('h');
__builtin_ia32_pause();
putchar('i');
putchar('\n');
sleep(100000);
}
}

View File

@@ -15,7 +15,7 @@ _syscall_entrypoint:
; Do very complicated stuff here
call syscall_impl
mov r11, 0x10016 ; TASK_POINTER->entry_ksp_val
mov r11, 0x10016 ; TASK_POINTER->ret_sp_val
mov rsp, [r11]
mov rcx, r15
o64 sysret

View File

@@ -12,10 +12,14 @@
#include "misc.hpp"
#include "tty.hpp"
// Don't forget the correct order
// Shockingly, it doesn't immediately break and even something simple as putchar works
// even with completely broken 16-bit segments somehow
// But what happens with something more complex is completely bonkers
struct STAR {
unsigned ret_cs_ss : 16;
unsigned call_cs_ss : 16;
unsigned unused : 32;
unsigned call_cs_ss : 16;
unsigned ret_cs_ss : 16;
} __attribute__((packed));
static_assert(sizeof(STAR) == 8);
@@ -46,10 +50,17 @@ uint64_t syscall_putchar(char c) {
return 0;
}
uint64_t syscall_sleep(uint64_t micros) {
sleep_self(micros);
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);
case SYSCALL_SLEEP_ID:
return syscall_sleep(a1_rsi);
default:
return -1;
}

View File

@@ -26,7 +26,11 @@ void sanity_check_frame(struct task_frame *cur_frame) {
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!");
assert2((cur_frame->ss == GDTSEL(gdt_data) || cur_frame->ss == GDTSEL(gdt_data_user)) | 0x3, "SS wrong!");
assert(cur_frame->ss != 0);
assert(cur_frame->cs != 0);
assert(cur_frame->sp != 0);
assert2((cur_frame->ss == GDTSEL(gdt_data) || (cur_frame->ss == GDTSEL(gdt_data_user)) | 0x3), "SS wrong!");
assert2((cur_frame->cs == GDTSEL(gdt_code) || (cur_frame->ss == GDTSEL(gdt_code_user)) | 0x3), "CS wrong!");
}
std::atomic<uint64_t> max_pid = 0;
@@ -158,8 +162,8 @@ struct Task *new_utask(void (*fn)(), const char *name) {
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;
taskptr_real->entry_ksp_val = newt->entry_ksp_val;
taskptr_real->ret_sp = 0x0;
void *ustack = newt->vma->mmap_mem(NULL, TASK_SS, 0, PAGE_RW | PAGE_USER);

View File

@@ -44,7 +44,7 @@ struct Task {
struct task_pointer {
Task *taskptr;
uint64_t *entry_ksp_val;
uint64_t entry_ksp_val;
uint64_t ret_sp;
} __attribute__((packed));

View File

@@ -22,8 +22,7 @@ void VMA::mark_taken(void *addr, size_t length) {
void VMA::map_kern() {
LockGuard l(space_lock);
for (uintptr_t i = (uint64_t) (0xFFFF800000000000ULL >> 39) & 0x01FF; i < 512; i++) {
assert(i >= 256);
for (uintptr_t i = 256; i < 512; i++) {
space->get_cr3()[i] = KERN_AddressSpace->get_cr3()[i];
}
}

View File

@@ -13,6 +13,7 @@ extern "C" {
#endif
#define SYSCALL_PUTCHAR_ID 1
#define SYSCALL_SLEEP_ID 2
#ifdef __cplusplus
}

View File

@@ -13,4 +13,14 @@ uint64_t putchar(char c) {
: "Di"(id), "Si"(c)
: "memory");
return res;
}
uint64_t sleep(uint64_t micros) {
uint64_t res;
uint64_t id = SYSCALL_SLEEP_ID;
asm("syscall"
: "=r"(res)
: "Di"(id), "Si"(micros)
: "memory");
return res;
}

View File

@@ -13,6 +13,7 @@ extern "C" {
#endif
uint64_t putchar(char c);
uint64_t sleep(uint64_t micros);
#ifdef __cplusplus
}