give each thread a syscall stack instead of the silliness from before
This commit is contained in:
parent
6d9c3f7794
commit
a3575b8997
5 changed files with 63 additions and 131 deletions
|
|
@ -18,6 +18,11 @@
|
|||
bits 64
|
||||
default rel
|
||||
|
||||
section .bss
|
||||
|
||||
resb 16384
|
||||
temporary_stack:
|
||||
|
||||
section .text
|
||||
|
||||
;referenced in process.c
|
||||
|
|
@ -42,3 +47,9 @@ thread_start:
|
|||
xor r15, r15
|
||||
|
||||
o64 sysret
|
||||
|
||||
;referenced in process.c
|
||||
global with_temporary_stack
|
||||
with_temporary_stack:
|
||||
mov rsp, temporary_stack
|
||||
jmp rdi
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include "framebuffer.h"
|
||||
#include "ipc-dgram.h"
|
||||
#include "scheduler.h"
|
||||
#include "syscalls.h"
|
||||
#include "process.h"
|
||||
#include "utility.h"
|
||||
#include "paging.h"
|
||||
|
|
@ -446,6 +445,8 @@ int syscall_start_elf(const char *path, const struct process_start_info *info) {
|
|||
|
||||
void destroy_process(struct process *process) {
|
||||
|
||||
assert(process->n_threads == 0)
|
||||
|
||||
if (process->files) {
|
||||
for (int i = 0; i < process->files_buffer_size; ++i)
|
||||
if (process->files[i].fs != 0)
|
||||
|
|
@ -499,23 +500,23 @@ void destroy_thread(struct thread *thread) {
|
|||
|
||||
assert(thread->process->n_threads >= 1)
|
||||
|
||||
if (thread->process->n_threads == 1)
|
||||
--thread->process->n_threads;
|
||||
|
||||
for (void *p = thread->syscall_stack_bottom; p < thread->syscall_stack_top; p += 4096)
|
||||
unmap_and_free_kernel_page(p);
|
||||
|
||||
if (thread->process->n_threads == 0)
|
||||
destroy_process(thread->process);
|
||||
|
||||
else {
|
||||
|
||||
--thread->process->n_threads;
|
||||
|
||||
else
|
||||
for (void *p = thread->stack_bottom; p < thread->stack_top; p += 4096)
|
||||
unmap_page_for_process(thread->process, p);
|
||||
|
||||
}
|
||||
|
||||
heap_dealloc(thread, sizeof(struct thread));
|
||||
|
||||
}
|
||||
|
||||
#define INITIAL_STACK_SIZE (16 << 20)
|
||||
#define INITIAL_SYSCALL_STACK_SIZE 16384
|
||||
|
||||
void create_thread(struct process *process, struct thread *thread_out) {
|
||||
|
||||
|
|
@ -539,9 +540,19 @@ void create_thread(struct process *process, struct thread *thread_out) {
|
|||
|
||||
}
|
||||
|
||||
void *syscall_stack_bottom = find_free_kernel_region(INITIAL_SYSCALL_STACK_SIZE);
|
||||
|
||||
for (int i = 0; i < INITIAL_SYSCALL_STACK_SIZE / 4096; ++i) {
|
||||
uint64_t pma = take_free_physical_page();
|
||||
map_in_kernel_page_table(
|
||||
pma, syscall_stack_bottom + i * 4096, 1, 0);
|
||||
}
|
||||
|
||||
thread_out->process = process;
|
||||
thread_out->stack_bottom = stack_bottom_vma;
|
||||
thread_out->stack_top = stack_bottom_vma + INITIAL_STACK_SIZE;
|
||||
thread_out->syscall_stack_bottom = syscall_stack_bottom;
|
||||
thread_out->syscall_stack_top = syscall_stack_bottom + INITIAL_SYSCALL_STACK_SIZE;
|
||||
|
||||
++process->n_threads;
|
||||
|
||||
|
|
@ -553,15 +564,23 @@ void create_thread(struct process *process, struct thread *thread_out) {
|
|||
|
||||
struct thread *running_thread = 0;
|
||||
|
||||
//defined in process.asm.
|
||||
//function should not return.
|
||||
[[noreturn]] void with_temporary_stack(void (*function)());
|
||||
|
||||
[[noreturn]] static void syscall_end_thread_with_temporary_stack() {
|
||||
destroy_syscall_stack(most_recent_syscall_stack);
|
||||
|
||||
assert(running_thread != 0)
|
||||
|
||||
struct thread *the_thread = running_thread;
|
||||
running_thread = 0;
|
||||
|
||||
destroy_thread(the_thread);
|
||||
resume_next_continuation();
|
||||
|
||||
}
|
||||
|
||||
[[noreturn]] void syscall_end_thread() {
|
||||
assert(running_thread != 0)
|
||||
destroy_thread(running_thread);
|
||||
running_thread = 0;
|
||||
with_temporary_stack(&syscall_end_thread_with_temporary_stack);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ struct process {
|
|||
//return value might be invalidated by future allocation of file handles for this process.
|
||||
struct process_file_info *get_file_info(struct process *process, file_handle_t handle);
|
||||
|
||||
//layout used in syscalls.asm
|
||||
struct thread {
|
||||
|
||||
struct process *process;
|
||||
|
|
@ -91,6 +92,10 @@ struct thread {
|
|||
void *stack_bottom;
|
||||
void *stack_top;
|
||||
|
||||
//both page-aligned
|
||||
void *syscall_stack_bottom;
|
||||
void *syscall_stack_top;
|
||||
|
||||
};
|
||||
|
||||
extern struct thread *running_thread;
|
||||
|
|
@ -105,6 +110,7 @@ void map_page_for_process(
|
|||
void *virtual_base, int writable, int executable, int owned);
|
||||
|
||||
//virtual base must be page-aligned, in bottom p3, and not zero.
|
||||
//also frees physical page if owned by process.
|
||||
void unmap_page_for_process(
|
||||
struct process *process, void *virtual_base);
|
||||
|
||||
|
|
@ -127,6 +133,7 @@ struct process *start_elf(const char *uri);
|
|||
int syscall_start_elf(const char *path, const struct process_start_info *info);
|
||||
|
||||
void destroy_process(struct process *process);
|
||||
//must not be called with syscall stack of the thread being destroyed
|
||||
void destroy_thread(struct thread *thread);
|
||||
|
||||
[[noreturn]] void syscall_illegal_args();
|
||||
|
|
|
|||
|
|
@ -18,133 +18,42 @@
|
|||
bits 64
|
||||
default rel
|
||||
|
||||
extern destroy_syscall_stack
|
||||
extern create_syscall_stack
|
||||
;defined in syscalls.c
|
||||
extern syscall_entry_c
|
||||
|
||||
section .bss
|
||||
|
||||
resb 1 << 15
|
||||
temp_syscall_stack:
|
||||
|
||||
available_syscall_stack_count equ 128
|
||||
available_syscall_stacks:
|
||||
resq available_syscall_stack_count
|
||||
|
||||
global most_recent_syscall_stack
|
||||
most_recent_syscall_stack:
|
||||
resq 1
|
||||
extern running_thread
|
||||
|
||||
section .text
|
||||
|
||||
;system call number is in rax.
|
||||
;system call arguments are in rdi, rsi, rdx.
|
||||
;system call returns a value in rax.
|
||||
;depends on layout of struct thread from process.h
|
||||
syscall_entry:
|
||||
mov r8, qword [running_thread]
|
||||
test r8, r8
|
||||
jz .assert_fail
|
||||
|
||||
xor r8, r8
|
||||
.find_stack_loop:
|
||||
|
||||
mov r9, qword [available_syscall_stacks + r8 * 8]
|
||||
test r9, r9
|
||||
jnz .got_syscall_stack
|
||||
|
||||
inc r8
|
||||
cmp r8, available_syscall_stack_count
|
||||
jne .find_stack_loop
|
||||
|
||||
mov qword [temp_syscall_stack - 8], rsp
|
||||
mov rsp, temp_syscall_stack - 8
|
||||
push r11
|
||||
push rcx
|
||||
push rax
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
|
||||
call create_syscall_stack
|
||||
mov r9, rax
|
||||
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rax
|
||||
pop rcx
|
||||
pop r11
|
||||
pop rsp
|
||||
|
||||
jmp .common
|
||||
|
||||
.got_syscall_stack:
|
||||
mov qword [available_syscall_stacks + r8 * 8], 0
|
||||
|
||||
.common:
|
||||
mov qword [r9 - 8], rsp
|
||||
mov rsp, r9
|
||||
mov qword [most_recent_syscall_stack], rsp
|
||||
mov r8, qword [r8 + 32]
|
||||
mov qword [r8 - 8], rsp
|
||||
mov rsp, r8
|
||||
sub rsp, 8
|
||||
push r11
|
||||
push rcx
|
||||
push r11
|
||||
|
||||
mov rcx, rax
|
||||
call syscall_entry_c
|
||||
|
||||
pop rcx
|
||||
pop r11
|
||||
|
||||
xor r8, r8
|
||||
.find_place_to_put_stack:
|
||||
|
||||
mov r9, qword [available_syscall_stacks + r8 * 8]
|
||||
test r9, r9
|
||||
jz .got_place
|
||||
|
||||
inc r8
|
||||
cmp r8, available_syscall_stack_count
|
||||
jne .find_stack_loop
|
||||
|
||||
mov rdi, rsp
|
||||
add rdi, 8
|
||||
|
||||
pop rsp
|
||||
|
||||
mov qword [temp_syscall_stack - 8], rsp
|
||||
mov rsp, temp_syscall_stack - 8
|
||||
push rax
|
||||
push rcx
|
||||
push r11
|
||||
|
||||
call destroy_syscall_stack
|
||||
|
||||
pop r11
|
||||
pop rcx
|
||||
pop rax
|
||||
jmp .common_2
|
||||
|
||||
.got_place:
|
||||
mov r9, rsp
|
||||
add r9, 8
|
||||
mov qword [available_syscall_stacks + r8 * 8], r9
|
||||
|
||||
.common_2:
|
||||
pop rsp
|
||||
o64 sysret
|
||||
|
||||
.assert_fail:
|
||||
ud2
|
||||
|
||||
global init_syscalls
|
||||
init_syscalls:
|
||||
sub rsp, 8
|
||||
mov qword [rsp], 0
|
||||
|
||||
.create_stack_loop:
|
||||
call create_syscall_stack
|
||||
mov rdi, qword [rsp]
|
||||
mov qword [available_syscall_stacks + rdi * 8], rax
|
||||
inc qword [rsp]
|
||||
cmp rdi, available_syscall_stack_count - 1
|
||||
jne .create_stack_loop
|
||||
|
||||
add rsp, 8
|
||||
|
||||
mov ecx, 0xc0000080
|
||||
rdmsr
|
||||
or al, 0x01
|
||||
|
|
@ -167,8 +76,3 @@ init_syscalls:
|
|||
wrmsr
|
||||
|
||||
ret
|
||||
|
||||
global with_temporary_stack
|
||||
with_temporary_stack:
|
||||
mov rsp, temp_syscall_stack
|
||||
jmp rdi
|
||||
|
|
|
|||
|
|
@ -25,12 +25,3 @@ void init_syscalls();
|
|||
void register_syscall(
|
||||
int number,
|
||||
uint64_t (*handler)(uint64_t arg1, uint64_t arg2, uint64_t arg3));
|
||||
|
||||
//the top of the syscall stack of the most recently started syscall.
|
||||
//kind of a hack, used in the end_thread syscall to deallocate that stack
|
||||
//and in the fork_thread syscall to copy the stack.
|
||||
extern void *most_recent_syscall_stack;
|
||||
|
||||
//also kind of a hack. switches to temporary stack and runs f with that stack.
|
||||
//f should not return. this does not touch most_recent_syscall_stack.
|
||||
[[noreturn]] void with_temporary_stack(void (*f)());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue