[USER] System calls

This commit is contained in:
Thomas Lovén 2016-12-06 15:50:35 +01:00
parent 63b3c3f2c0
commit a7d2b24a79
9 changed files with 166 additions and 2 deletions

View File

@ -1,8 +1,10 @@
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
(void) argc;
(void) argv;
int i=0;
for(;;)i++;
asm("syscall" :: "a" (0x3FF), "D" ("Hello, world!\n"));
for(;;);
return 0;
}

View File

@ -9,6 +9,8 @@
#include <string.h>
#include <cpu.h>
#include <elf.h>
#include <syscall.h>
#include <cpuid.h>
int kmain(uint64_t multiboot_magic, void *multiboot_data)
{
@ -24,6 +26,8 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
cpu_init();
pit_init();
debug_info("Syscall enabled:%d\n", CPUID_FEATURE_SYSCALL);
process_t *p1 = process_spawn(0);
thread_t *th = exec_elf(p1, mboot_data.init);
scheduler_insert(th);

View File

@ -7,6 +7,7 @@
#include <mem.h>
#include <gdt.h>
#include <string.h>
#include <syscall.h>
cpu_t cpus[MAX_NUMCPU];
unsigned int num_cpu = 0;
@ -38,6 +39,7 @@ void init_cpu()
gdt_init();
sse_init();
scheduler_init();
syscall_init();
}
void cpu_init()

View File

@ -14,6 +14,7 @@
#define GS_OFFSET_CPU 0
#define GS_OFFSET_STATE 40
#define GS_OFFSET_STACK 48
#define GS_OFFSET_SCTEMP 56
#ifndef __ASSEMBLER__
#include <stdint.h>
@ -31,6 +32,7 @@ typedef struct cpu_t
uint64_t is_bsp;
uint64_t current_state; // 40
void *kernel_stack; // 48
uint64_t syscall_temp; // 56
thread_t *current_thread;
thread_t *last_thread;
process_t *current_process;

View File

@ -66,6 +66,7 @@
#define INT_APIC_ERROR 0x45
#define INT_APIC_SPUR 0xFF
#define INT_SYSCALL 0x80
#define RFLAGS_IOPL (3<<12)
#define RFLAGS_IOPL1 (1<<12)

41
kernel/include/syscall.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
void syscall_init();
typedef long (*syscall_handler_t)(long num, long, long, long, long, long, long);
#define SYSCALL_DECL(name) \
long syscall_##name(long, long, long, long, long, long, long)
#define SYSCALL_DEF(name) \
long syscall_##name(long num, long _a1, long _a2, long _a3, long _a4, long _a5, long _a6)
#define _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,t6,n6) \
(void)num; \
t1 n1 = (t1)_a1; \
(void)n1; \
t2 n2 = (t2)_a2; \
(void)n2; \
t3 n3 = (t3)_a3; \
(void)n3; \
t4 n4 = (t4)_a4; \
(void)n4; \
t5 n5 = (t5)_a5; \
(void)n5; \
t6 n6 = (t6)_a6; \
(void)n6;
#define _SYSCALL_INIT5(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,t5,n5,long,__a6)
#define _SYSCALL_INIT4(t1,n1,t2,n2,t3,n3,t4,n4) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,t4,n4,long,__a5,long,__a6)
#define _SYSCALL_INIT3(t1,n1,t2,n2,t3,n3) _SYSCALL_INIT6(t1,n1,t2,n2,t3,n3,long,__a4,long,__a5,long,__a6)
#define _SYSCALL_INIT2(t1,n1,t2,n2) _SYSCALL_INIT6(t1,n1,t2,n2,long,__a3,long,__a4,long,__a5,long,__a6)
#define _SYSCALL_INIT1(t1,n1) _SYSCALL_INIT6(t1,n1,long,__a2,long,__a3,long,__a4,long,__a5,long,__a6)
#define _SYSCALL_INIT0() _SYSCALL_INIT6(long,__a1,long,__a2,long,__a3,long,__a4,long,__a5,long,__a6)
#define __SYSCALL_NARGS(a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,n,...) n
#define _SYSCALL_NARGS(...) __SYSCALL_NARGS(__VA_ARGS__,6,6,5,5,4,4,3,3,2,2,1,1,0,0)
#define __SYSCALL_CONCAT(a,b) a##b
#define _SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT(a,b)
#define _SYSCALL_INIT(a,...) _SYSCALL_CONCAT(a, _SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
#define SYSCALL_INIT(...) _SYSCALL_INIT(_SYSCALL_INIT,__VA_ARGS__)
#define SYSCALL_REGISTER(name, num) syscall_handlers[num] = syscall_##name

View File

@ -64,6 +64,15 @@ isr_return:
pop r13
pop r14
pop r15
// Jump to syscall_return if we're in a syscall
push rax
mov rax, [rsp + 8]
cmp rax, INT_SYSCALL
.extern syscall_return
jz syscall_return
pop rax
// Pop error code and fault number
add rsp, 16
iretq

65
kernel/syscall/syscall.c Normal file
View File

@ -0,0 +1,65 @@
#include <syscall.h>
#include <debug.h>
#include <int.h>
#include <msr.h>
#include <gdt.h>
#include <registers.h>
extern void syscall_entry();
syscall_handler_t syscall_handlers[1024];
SYSCALL_DECL(debug);
registers_t *syscall_handler(registers_t *r)
{
// Syscall number: RAX
// Order of arguments:
// RDI
// RSI
// RDX
// R10
// R8
// R9
// stack
//
// Return value:
// RAX
if(syscall_handlers[r->rax])
{
r->rax = syscall_handlers[r->rax](r->rax, r->rdi, r->rsi, r->rdx, r->r10, r->r8, r->r9);
return r;
}
debug_error("Unknown syscall, No:%d\n", r->rax);
debug("syscall_%d(%x, %x, %x, %x, %x, %x)\n", r->rax, r->rdi, r->rsi, r->rdx, r->r10, r->r8, r->r9);
for(;;);
}
int syscall_installed = 0;
void syscall_init()
{
msr_write(MSR_REG_STAR, (((uint64_t)SEG_KDATA | 0x3)<<48 | ((uint64_t)SEG_KCODE)<<32));
msr_write(MSR_REG_LSTAR, (uint64_t)syscall_entry);
msr_write(MSR_REG_EFER, msr_read(MSR_REG_EFER)| 1);
msr_write(MSR_REG_FMASK, RFLAGS_IF);
if(!syscall_installed)
{
register_int_handler(INT_SYSCALL, syscall_handler);
syscall_installed = 1;
memset(syscall_handlers, 0, 1024*sizeof(syscall_handler_t));
SYSCALL_REGISTER(debug, 0x3FF);
}
}
SYSCALL_DEF(debug)
{
SYSCALL_INIT(char*, message);
debug_puts(message);
return 0;
}

View File

@ -0,0 +1,38 @@
#include <mem.h>
#include <gdt.h>
#include <int.h>
#include <cpu.h>
.intel_syntax noprefix
.global syscall_entry
.global syscall_return
.extern syscall_handler
syscall_entry:
swapgs
mov [gs:GS_OFFSET_SCTEMP], rsp
mov rsp, [gs:GS_OFFSET_STACK]
// Prepare a fake interrupt stack
pushq SEG_UDATA // SS
push [gs:GS_OFFSET_SCTEMP] // RSP
push r11 // RFLAGS
pushq SEG_UCODE // CS
push rcx // RIP
pushq 0 // Error code
pushq INT_SYSCALL // Interrupt id
swapgs
jmp isr_common
syscall_return:
pop rax
add rsp, 16
pop rcx
add rsp, 8
pop r11
pop rsp
sysretq