Implement fast syscall/sysret for sytem calls

This commit is contained in:
Justin C. Miller
2019-03-13 23:51:29 -07:00
parent 97e8f2c69a
commit f7558e3d18
9 changed files with 77 additions and 21 deletions

View File

@@ -8,17 +8,17 @@ _start:
xor rbp, rbp ; Sentinel rbp xor rbp, rbp ; Sentinel rbp
mov rax, 5 ; GETPID syscall mov rax, 5 ; GETPID syscall
int 0xee syscall ; int 0xee
mov [mypid], rax mov [mypid], rax
mov rax, 8 ; FORK syscall mov rax, 8 ; FORK syscall
int 0xee syscall ; int 0xee
mov [mychild], rax mov [mychild], rax
mov r12, [mypid] mov r12, [mypid]
mov r13, [mychild] mov r13, [mychild]
mov rax, 1 ; DEBUG syscall mov rax, 1 ; DEBUG syscall
int 0xee syscall ; int 0xee
cmp r12, 1 cmp r12, 1
je .dosend je .dosend
@@ -32,7 +32,7 @@ _start:
mov rax, 1 ; MESSAGE syscall mov rax, 1 ; MESSAGE syscall
;mov rax, 0 ; NOOP syscall ;mov rax, 0 ; NOOP syscall
;syscall ;syscall
int 0xee syscall ; int 0xee
inc r11 inc r11
cmp r11, 2 cmp r11, 2
@@ -41,7 +41,7 @@ _start:
mov rax, 4 ; SLEEP syscall mov rax, 4 ; SLEEP syscall
; syscall ; syscall
int 0xee syscall ; int 0xee
add rbx, 20 add rbx, 20
@@ -51,11 +51,11 @@ _start:
.dosend: .dosend:
mov rax, 6 ; SEND syscall mov rax, 6 ; SEND syscall
mov rdi, 2 ; target is pid 2 mov rdi, 2 ; target is pid 2
int 0xee syscall ; int 0xee
jmp .preloop jmp .preloop
.doreceive: .doreceive:
mov rax, 7 ; RECEIVE syscall mov rax, 7 ; RECEIVE syscall
mov rdi, 1 ; source is pid 2 mov rdi, 1 ; source is pid 2
int 0xee syscall ; int 0xee
jmp .preloop jmp .preloop

View File

@@ -6,6 +6,9 @@
#define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value)); #define print_reg(name, value) cons->printf(" %s: %016lx\n", name, (value));
size_t __counter_syscall_enter = 0;
size_t __counter_syscall_sysret = 0;
void void
print_regs(const cpu_state &regs) print_regs(const cpu_state &regs)
{ {

View File

@@ -12,6 +12,9 @@ extern "C" {
} }
extern size_t __counter_syscall_enter;
extern size_t __counter_syscall_sysret;
void print_regs(const cpu_state &regs); void print_regs(const cpu_state &regs);
void print_stack(const cpu_state &regs); void print_stack(const cpu_state &regs);
void print_stacktrace(int skip = 0); void print_stacktrace(int skip = 0);

View File

@@ -4,38 +4,37 @@ extern isr_handler
global isr_handler_prelude global isr_handler_prelude
isr_handler_prelude: isr_handler_prelude:
push_all_and_segments push_all_and_segments
check_swap_gs
mov rdi, rsp mov rdi, rsp
mov rsi, rsp mov rsi, rsp
call isr_handler call isr_handler
mov rsp, rax mov rsp, rax
jmp isr_handler_return
pop_all_and_segments
add rsp, 16 ; because the ISRs added err/num
sti
iretq
extern irq_handler extern irq_handler
global irq_handler_prelude global irq_handler_prelude
irq_handler_prelude: irq_handler_prelude:
push_all_and_segments push_all_and_segments
check_swap_gs
mov rdi, rsp mov rdi, rsp
mov rsi, rsp mov rsi, rsp
call irq_handler call irq_handler
mov rsp, rax mov rsp, rax
; fall through to isr_handler_return
global isr_handler_return
isr_handler_return:
check_swap_gs
pop_all_and_segments pop_all_and_segments
add rsp, 16 ; because the ISRs added err/num add rsp, 16 ; because the ISRs added err/num
sti
iretq iretq
%macro EMIT_ISR 2 %macro EMIT_ISR 2
global %1 global %1
%1: %1:
cli
push 0 push 0
push %2 push %2
jmp isr_handler_prelude jmp isr_handler_prelude
@@ -44,7 +43,6 @@ irq_handler_prelude:
%macro EMIT_EISR 2 %macro EMIT_EISR 2
global %1 global %1
%1: %1:
cli
push %2 push %2
jmp isr_handler_prelude jmp isr_handler_prelude
%endmacro %endmacro
@@ -52,7 +50,6 @@ irq_handler_prelude:
%macro EMIT_IRQ 2 %macro EMIT_IRQ 2
global %1 global %1
%1: %1:
cli
push 0 push 0
push %2 push %2
jmp irq_handler_prelude jmp irq_handler_prelude

View File

@@ -18,6 +18,15 @@ ramdisk_process_loader:
mov rdx, rcx mov rdx, rcx
call load_process call load_process
swapgs
xor rax, rax
mov ax, ss
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
pop_all_and_segments pop_all_and_segments
add rsp, 16 ; because the ISRs add err/num add rsp, 16 ; because the ISRs add err/num
iretq iretq

View File

@@ -44,4 +44,13 @@
pop rax pop rax
%endmacro %endmacro
%macro check_swap_gs 0
mov rax, [rsp+0x90]
and rax, 0x03 ; mask out the RPL
cmp rax, 0x03
jne %%noswapgs
swapgs
%%noswapgs:
%endmacro
; vim: ft=asm ; vim: ft=asm

View File

@@ -1,6 +1,7 @@
#include "apic.h" #include "apic.h"
#include "console.h" #include "console.h"
#include "cpu.h" #include "cpu.h"
#include "debug.h"
#include "gdt.h" #include "gdt.h"
#include "interrupts.h" #include "interrupts.h"
#include "io.h" #include "io.h"
@@ -26,6 +27,14 @@ extern "C" {
void load_process(const void *image_start, size_t bytes, process *proc, cpu_state state); void load_process(const void *image_start, size_t bytes, process *proc, cpu_state state);
}; };
struct cpu_data
{
uintptr_t rsp0;
uintptr_t rsp3;
};
static cpu_data bsp_cpu_data;
scheduler::scheduler(lapic *apic) : scheduler::scheduler(lapic *apic) :
m_apic(apic), m_apic(apic),
m_next_pid(1) m_next_pid(1)
@@ -181,6 +190,7 @@ void
scheduler::start() scheduler::start()
{ {
log::info(logs::task, "Starting scheduler."); log::info(logs::task, "Starting scheduler.");
wrmsr(msr::ia32_gs_base, reinterpret_cast<uintptr_t>(&bsp_cpu_data));
m_tick_count = m_apic->enable_timer(isr::isrTimer, quantum_micros, false); m_tick_count = m_apic->enable_timer(isr::isrTimer, quantum_micros, false);
} }
@@ -236,7 +246,6 @@ void scheduler::prune(uint64_t now)
uintptr_t uintptr_t
scheduler::schedule(uintptr_t rsp0) scheduler::schedule(uintptr_t rsp0)
{ {
// TODO: lol a real clock // TODO: lol a real clock
static uint64_t now = 0; static uint64_t now = 0;
@@ -262,7 +271,8 @@ scheduler::schedule(uintptr_t rsp0)
// Set rsp0 to after the end of the about-to-be-popped cpu state // Set rsp0 to after the end of the about-to-be-popped cpu state
tss_set_stack(0, rsp0 + sizeof(cpu_state)); tss_set_stack(0, rsp0 + sizeof(cpu_state));
wrmsr(msr::ia32_kernel_gs_base, rsp0); bsp_cpu_data.rsp0 = rsp0;
// Swap page tables // Swap page tables
page_table *pml4 = m_current->pml4; page_table *pml4 = m_current->pml4;

View File

@@ -52,6 +52,8 @@ syscall_dispatch(uintptr_t return_rsp, cpu_state &regs)
cons->printf("\nProcess %u: Received DEBUG syscall\n", p->pid); cons->printf("\nProcess %u: Received DEBUG syscall\n", p->pid);
cons->set_color(); cons->set_color();
print_regs(regs); print_regs(regs);
cons->printf("\n Syscall enters: %8d\n", __counter_syscall_enter);
cons->printf(" Syscall sysret: %8d\n", __counter_syscall_sysret);
break; break;
case syscall::message: case syscall::message:

View File

@@ -1,21 +1,44 @@
%include "push_all.inc" %include "push_all.inc"
extern __counter_syscall_enter
extern __counter_syscall_sysret
extern syscall_handler extern syscall_handler
extern isr_handler_return
global syscall_handler_prelude global syscall_handler_prelude
syscall_handler_prelude: syscall_handler_prelude:
push 0 ; ss, doesn't matter here swapgs
mov [gs:0x08], rsp
mov rsp, [gs:0x00]
push 0x23 ; ss
push rsp push rsp
pushf pushf
push 0 ; cs, doesn't matter here push 0x2b ; cs
push rcx ; user rip push rcx ; user rip
push 0 ; bogus interrupt push 0 ; bogus interrupt
push 0 ; bogus errorcode push 0 ; bogus errorcode
push_all_and_segments push_all_and_segments
inc qword [rel __counter_syscall_enter]
mov rax, [gs:0x08]
mov [rsp + 0x98], rax
mov rax, [rsp + 0x70]
mov rdi, rsp mov rdi, rsp
call syscall_handler call syscall_handler
mov rsp, rax mov rsp, rax
mov rax, [rsp + 0x90]
and rax, 0x3
cmp rax, 0x3
jne isr_handler_return
inc qword [rel __counter_syscall_sysret]
swapgs
pop_all_and_segments pop_all_and_segments
add rsp, 16 ; ignore bogus interrupt / error add rsp, 16 ; ignore bogus interrupt / error
pop rcx ; user rip pop rcx ; user rip