[USER] System calls
This commit is contained in:
parent
63b3c3f2c0
commit
a7d2b24a79
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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
41
kernel/include/syscall.h
Normal 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
|
@ -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
65
kernel/syscall/syscall.c
Normal 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;
|
||||
}
|
38
kernel/syscall/syscall_entry.S
Normal file
38
kernel/syscall/syscall_entry.S
Normal 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
|
Loading…
x
Reference in New Issue
Block a user