mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
system calls
This commit is contained in:
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
objects := $(patsubst %.c,%.o,$(wildcard *.c)) israsm.o context.o
|
objects := $(patsubst %.c,%.o,$(wildcard *.c)) israsm.o context.o syscall.o
|
||||||
subdirs=boot
|
subdirs=boot
|
||||||
OBJPATH=$(OBJDIR)/arch/${TARGET}/
|
OBJPATH=$(OBJDIR)/arch/${TARGET}/
|
||||||
export
|
export
|
||||||
@@ -19,3 +19,7 @@ context.o: context.asm
|
|||||||
nasm -f elf64 -o $@ $<
|
nasm -f elf64 -o $@ $<
|
||||||
mkdir -p $(OBJPATH)
|
mkdir -p $(OBJPATH)
|
||||||
cp $@ $(OBJPATH)/$@
|
cp $@ $(OBJPATH)/$@
|
||||||
|
syscall.o: syscall.asm
|
||||||
|
nasm -f elf64 -o $@ $<
|
||||||
|
mkdir -p $(OBJPATH)
|
||||||
|
cp $@ $(OBJPATH)/$@
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
global arch_switchcontext
|
global arch_switchcontext
|
||||||
arch_switchcontext:
|
arch_switchcontext:
|
||||||
mov rsp,rdi
|
mov rsp,rdi
|
||||||
add rsp, 8 ; cr2
|
add rsp, 24 ; cr2 gs fs
|
||||||
pop rax
|
|
||||||
mov gs,rax
|
mov rbx,es
|
||||||
pop rax
|
|
||||||
mov fs,rax
|
|
||||||
pop rax
|
pop rax
|
||||||
|
cmp rax,rbx
|
||||||
|
jne .segswap
|
||||||
|
add rsp,8 ; ds
|
||||||
|
jmp .genreg
|
||||||
|
.segswap:
|
||||||
|
swapgs
|
||||||
mov es,rax
|
mov es,rax
|
||||||
pop rax
|
pop rax
|
||||||
mov ds,rax
|
mov ds,rax
|
||||||
|
|
||||||
|
.genreg:
|
||||||
pop rax
|
pop rax
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rcx
|
pop rcx
|
||||||
@@ -27,6 +33,4 @@ arch_switchcontext:
|
|||||||
pop rbp
|
pop rbp
|
||||||
add rsp,8 ; remove error code
|
add rsp,8 ; remove error code
|
||||||
|
|
||||||
swapgs
|
|
||||||
|
|
||||||
iretq
|
iretq
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
// syscall, sse, etc
|
// syscall, sse, etc
|
||||||
// for the current cpu
|
// for the current cpu
|
||||||
|
|
||||||
|
extern void asm_syscall_entry();
|
||||||
|
|
||||||
void cpu_state_init(){
|
void cpu_state_init(){
|
||||||
|
|
||||||
// syscall
|
// syscall
|
||||||
@@ -28,7 +30,7 @@ void cpu_state_init(){
|
|||||||
star |= (uint64_t)0x28 << 32;
|
star |= (uint64_t)0x28 << 32;
|
||||||
|
|
||||||
wrmsr(MSR_STAR, star);
|
wrmsr(MSR_STAR, star);
|
||||||
wrmsr(MSR_LSTAR, 0xDEADBEEF); // FIXME add 64 bit handler here
|
wrmsr(MSR_LSTAR, asm_syscall_entry);
|
||||||
wrmsr(MSR_CSTAR, 0); // no compat mode syscall handler
|
wrmsr(MSR_CSTAR, 0); // no compat mode syscall handler
|
||||||
wrmsr(MSR_FMASK, 0x200); // disable interrupts on syscall
|
wrmsr(MSR_FMASK, 0x200); // disable interrupts on syscall
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ static void reloadgdtr(){
|
|||||||
|
|
||||||
gdtr.offset = &arch_getcls()->gdt;
|
gdtr.offset = &arch_getcls()->gdt;
|
||||||
gdtr.size = sizeof(gdt_t) - 1;
|
gdtr.size = sizeof(gdt_t) - 1;
|
||||||
asm("lgdt (%%rax)" : : "a"(&gdtr) : "memory");
|
asm volatile("lgdt (%%rax)" : : "a"(&gdtr) : "memory");
|
||||||
asm("ltr %%ax" : : "a"(0x48));
|
asm volatile("ltr %%ax" : : "a"(0x48));
|
||||||
|
asm volatile("swapgs;mov $0, %%ax;mov %%ax, %%gs;mov %%ax, %%fs;swapgs;" : : : "ax");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdt_init(){
|
void gdt_init(){
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
// this will be pointed to by GS and will contain per cpu info
|
// this will be pointed to by GS and will contain per cpu info
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
|
void* kstack;
|
||||||
gdt_t gdt;
|
gdt_t gdt;
|
||||||
ist_t ist;
|
ist_t ist;
|
||||||
int lapicid;
|
int lapicid;
|
||||||
|
|||||||
@@ -4,10 +4,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint64_t gsbase, fsbase;
|
||||||
|
} arch_extraregs;
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint64_t cr2,gs,fs,es,ds,rax,rbx,rcx,rdx,r8,r9,r10,r11,r12,r13,r14,r15,rdi,rsi,rbp,error,rip,cs,rflags,rsp,ss;
|
uint64_t cr2,gs,fs,es,ds,rax,rbx,rcx,rdx,r8,r9,r10,r11,r12,r13,r14,r15,rdi,rsi,rbp,error,rip,cs,rflags,rsp,ss;
|
||||||
} arch_regs;
|
} arch_regs;
|
||||||
|
void arch_regs_saveextra(arch_extraregs* regs);
|
||||||
|
void arch_regs_setupextra(arch_extraregs* regs);
|
||||||
void arch_regs_setupkernel(arch_regs* regs, void* ip, void* stack, bool interrupts);
|
void arch_regs_setupkernel(arch_regs* regs, void* ip, void* stack, bool interrupts);
|
||||||
void arch_regs_setupuser(arch_regs* regs, void* ip, void* stack, bool interrupts);
|
void arch_regs_setupuser(arch_regs* regs, void* ip, void* stack, bool interrupts);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ section .text
|
|||||||
mov rax, gs
|
mov rax, gs
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
cmp rax,0x30
|
cmp rax,0x43
|
||||||
jmp .noswapgs
|
jmp .noswapgs
|
||||||
swapgs
|
swapgs
|
||||||
.noswapgs:
|
.noswapgs:
|
||||||
@@ -42,22 +42,18 @@ section .text
|
|||||||
|
|
||||||
%macro popregs 0
|
%macro popregs 0
|
||||||
|
|
||||||
add rsp, 8 ; cr2
|
add rsp, 24 ; cr2 gs fs
|
||||||
|
|
||||||
pop rax
|
pop rax
|
||||||
cmp rax,0x30
|
cmp rax,0x43
|
||||||
je .dontpopsegs
|
je .dontpopsegs
|
||||||
mov gs,rax
|
|
||||||
pop rax
|
|
||||||
mov fs,rax
|
|
||||||
pop rax
|
|
||||||
mov es,rax
|
mov es,rax
|
||||||
pop rax
|
pop rax
|
||||||
mov ds,rax
|
mov ds,rax
|
||||||
swapgs
|
swapgs
|
||||||
jmp .poprest
|
jmp .poprest
|
||||||
.dontpopsegs:
|
.dontpopsegs:
|
||||||
add rsp,24
|
add rsp,8 ; ds
|
||||||
|
|
||||||
.poprest:
|
.poprest:
|
||||||
pop rax
|
pop rax
|
||||||
|
|||||||
@@ -5,4 +5,5 @@
|
|||||||
void arch_setkernelstack(void* stack){
|
void arch_setkernelstack(void* stack){
|
||||||
|
|
||||||
arch_getcls()->ist.rsp0 = (uint64_t)stack;
|
arch_getcls()->ist.rsp0 = (uint64_t)stack;
|
||||||
|
arch_getcls()->kstack = stack;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
#include <arch/regs.h>
|
#include <arch/regs.h>
|
||||||
|
#include <arch/msr.h>
|
||||||
|
|
||||||
|
void arch_regs_saveextra(arch_extraregs* regs){
|
||||||
|
// user gs was swapped
|
||||||
|
regs->gsbase = rdmsr(MSR_KERNELGSBASE);
|
||||||
|
regs->fsbase = rdmsr(MSR_FSBASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_regs_setupextra(arch_extraregs* regs){
|
||||||
|
// gs will be swapped later
|
||||||
|
wrmsr(MSR_KERNELGSBASE, regs->gsbase);
|
||||||
|
wrmsr(MSR_FSBASE, regs->fsbase);
|
||||||
|
}
|
||||||
|
|
||||||
void arch_regs_setupkernel(arch_regs* regs, void* ip, void* stack, bool interrupts){
|
void arch_regs_setupkernel(arch_regs* regs, void* ip, void* stack, bool interrupts){
|
||||||
regs->rip = ip;
|
regs->rip = ip;
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
section .rodata
|
||||||
|
|
||||||
|
|
||||||
|
extern syscall_libc_log
|
||||||
|
func_count equ 1
|
||||||
|
|
||||||
|
|
||||||
|
func_table:
|
||||||
|
dq syscall_libc_log
|
||||||
|
|
||||||
|
section .text
|
||||||
|
global asm_syscall_entry
|
||||||
|
|
||||||
|
; the registers for the system call are:
|
||||||
|
; RETURN:
|
||||||
|
; rax -> ret value
|
||||||
|
; rdx -> errno
|
||||||
|
; PARAM:
|
||||||
|
; rax -> func
|
||||||
|
; rdi, rsi, rdx, r10, r8, r9 -> parameters
|
||||||
|
; clobbers: rax, rdx, rcx, r11
|
||||||
|
|
||||||
|
asm_syscall_entry:
|
||||||
|
swapgs
|
||||||
|
|
||||||
|
xchg rsp, [gs:0] ; get new stack
|
||||||
|
push qword [gs:0] ; save old stack
|
||||||
|
mov [gs:0], rsp ; return back the kernel stack
|
||||||
|
add qword [gs:0], 8 ; fix it
|
||||||
|
|
||||||
|
push rcx ; old rip
|
||||||
|
push r11 ; old rflags
|
||||||
|
|
||||||
|
mov r11, 0x30 ; kernel data
|
||||||
|
mov ds, r11
|
||||||
|
mov es, r11
|
||||||
|
|
||||||
|
; save C scratch registers
|
||||||
|
; rax is not saved because it will be the return value
|
||||||
|
; rdx is not saved because it will be the errno value
|
||||||
|
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push rcx
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
|
||||||
|
; system V C abi expects the third param to be in rcx
|
||||||
|
; but the param is in rdx because of the syscall instruction
|
||||||
|
|
||||||
|
mov rcx, rdx
|
||||||
|
|
||||||
|
call [func_table + rax * 8]
|
||||||
|
|
||||||
|
; now restore the scratch registers
|
||||||
|
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rcx
|
||||||
|
pop rsi
|
||||||
|
pop rdi
|
||||||
|
|
||||||
|
; restore entry state
|
||||||
|
|
||||||
|
mov r11, 0x40 ; user data
|
||||||
|
mov es,r11
|
||||||
|
mov ds,r11
|
||||||
|
|
||||||
|
pop r11
|
||||||
|
pop rcx
|
||||||
|
pop rsp
|
||||||
|
swapgs
|
||||||
|
|
||||||
|
o64 sysret
|
||||||
@@ -23,6 +23,7 @@ typedef struct _thread_t{
|
|||||||
struct _thread_t* prev;
|
struct _thread_t* prev;
|
||||||
struct _proc_t* proc;
|
struct _proc_t* proc;
|
||||||
arch_regs* regs;
|
arch_regs* regs;
|
||||||
|
arch_extraregs extraregs;
|
||||||
state_t state;
|
state_t state;
|
||||||
void* kernelstack;
|
void* kernelstack;
|
||||||
void* kernelstackbase;
|
void* kernelstackbase;
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef _SYSCALLS_H_INCLUDE
|
||||||
|
#define _SYSCALLS_H_INCLUDE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long ret;
|
||||||
|
long errno;
|
||||||
|
} syscallret;
|
||||||
|
|
||||||
|
syscallret syscall_libc_log(char* str);
|
||||||
|
|
||||||
|
#endif
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
objects := $(patsubst %.c,%.o,$(wildcard *.c))
|
objects := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||||
subdirs := mm sched
|
subdirs := mm sched syscalls
|
||||||
OBJPATH=$(OBJDIR)
|
OBJPATH=$(OBJDIR)
|
||||||
export
|
export
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ void sched_timerhook(arch_regs* regs){
|
|||||||
|
|
||||||
|
|
||||||
memcpy(current->regs, regs, sizeof(arch_regs));
|
memcpy(current->regs, regs, sizeof(arch_regs));
|
||||||
|
arch_regs_saveextra(¤t->extraregs);
|
||||||
|
|
||||||
spinlock_acquire(¤tqueue->lock);
|
spinlock_acquire(¤tqueue->lock);
|
||||||
|
|
||||||
@@ -198,6 +198,8 @@ static void switch_thread(thread_t* thread){
|
|||||||
|
|
||||||
arch_setkernelstack(thread->kernelstack);
|
arch_setkernelstack(thread->kernelstack);
|
||||||
|
|
||||||
|
arch_regs_setupextra(&thread->extraregs);
|
||||||
|
|
||||||
arch_switchcontext(thread->regs);
|
arch_switchcontext(thread->regs);
|
||||||
|
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
@@ -292,6 +294,8 @@ void sched_runinit(){
|
|||||||
_panic("Could not load init", 0);
|
_panic("Could not load init", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread->extraregs.gsbase = 0xFFFFFFFFDEADBEEF;
|
||||||
|
|
||||||
switch_thread(thread);
|
switch_thread(thread);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
objects := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||||
|
subdirs :=
|
||||||
|
OBJPATH=$(OBJDIR)
|
||||||
|
export
|
||||||
|
|
||||||
|
all: $(subdirs) $(objects)
|
||||||
|
for subdir in $(subdirs) ; do $(MAKE) -C $${subdir} ; done
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ $<
|
||||||
|
mkdir -p $(OBJPATH)
|
||||||
|
cp $@ $(OBJPATH)/$@
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include <kernel/syscalls.h>
|
||||||
|
#include <kernel/alloc.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
syscallret syscall_libc_log(char* str){
|
||||||
|
|
||||||
|
syscallret ret;
|
||||||
|
|
||||||
|
char* buf = alloc(strlen(str) + 1);
|
||||||
|
if(!buf){
|
||||||
|
ret.errno = ENOMEM;
|
||||||
|
ret.ret = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buf, str);
|
||||||
|
|
||||||
|
printf("%s", str);
|
||||||
|
|
||||||
|
ret.errno = 0;
|
||||||
|
ret.ret = 0;
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user