From 76e31b5e42913f09a1a00bf885a8fdf4282ebd07 Mon Sep 17 00:00:00 2001 From: Mathieu Strypsteen Date: Mon, 23 Dec 2024 21:07:06 +0100 Subject: [PATCH] Add syscall handler --- kernel/src/cpu/isr.rs | 1 + kernel/src/cpu/isr.s | 7 +++++++ kernel/src/cpu/syscall.s | 28 +++++++++++++++++++++++++++- kernel/src/cpu/usermode.s | 2 ++ kernel/src/sys/lapic.rs | 1 + kernel/src/sys/mod.rs | 1 + kernel/src/sys/syscall.rs | 2 ++ kernel/src/sys/task.rs | 8 +++++++- 8 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 kernel/src/sys/syscall.rs diff --git a/kernel/src/cpu/isr.rs b/kernel/src/cpu/isr.rs index dd1d5ca..a5443f3 100644 --- a/kernel/src/cpu/isr.rs +++ b/kernel/src/cpu/isr.rs @@ -22,6 +22,7 @@ global_asm!(include_str!("isr.s"), options(att_syntax)); #[repr(C)] #[derive(Clone, Copy)] pub struct ISRState { + pub ds: u64, pub rax: u64, pub rbx: u64, pub rcx: u64, diff --git a/kernel/src/cpu/isr.s b/kernel/src/cpu/isr.s index 3d84804..ded8a3d 100644 --- a/kernel/src/cpu/isr.s +++ b/kernel/src/cpu/isr.s @@ -31,10 +31,17 @@ isr_common: push %rcx push %rbx push %rax + mov %ds, %rax + push %rax mov %rsp, %rdi call isr_handler + pop %rax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs pop %rax pop %rbx pop %rcx diff --git a/kernel/src/cpu/syscall.s b/kernel/src/cpu/syscall.s index 7618096..1cb8aa5 100644 --- a/kernel/src/cpu/syscall.s +++ b/kernel/src/cpu/syscall.s @@ -6,4 +6,30 @@ syscall: mov %rsp, %gs:8 mov %gs:0, %rsp swapgs - jmp . + sti + push %r11 + push %r10 + push %r9 + push %r8 + push %rsi + push %rdi + push %rdx + push %rcx + push %rax + + call syscall_handler + + pop %rax + pop %rcx + pop %rdx + pop %rdi + pop %rsi + pop %r8 + pop %r9 + pop %r10 + pop %r11 + cli + swapgs + mov %gs:8, %rsp + swapgs + sysretq diff --git a/kernel/src/cpu/usermode.s b/kernel/src/cpu/usermode.s index 5bd79a6..81944ba 100644 --- a/kernel/src/cpu/usermode.s +++ b/kernel/src/cpu/usermode.s @@ -2,11 +2,13 @@ .global jump_usermode jump_usermode: + cli // Ensure consistency in segment registers mov $0x1b, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs + sti push $0x1b push $0 pushf diff --git a/kernel/src/sys/lapic.rs b/kernel/src/sys/lapic.rs index c0355f9..fd33939 100644 --- a/kernel/src/sys/lapic.rs +++ b/kernel/src/sys/lapic.rs @@ -41,6 +41,7 @@ pub fn send_eoi() { address.add(REGISTER_EOI).write_volatile(0); } } +// It's unsafe to get the LAPIC ID if interrupts are enabled, because the task can have migrated to a different core. pub fn get_current_lapic_id() -> usize { let address = ADDRESS.load(Ordering::SeqCst); let lapic_id = unsafe { address.add(REGISTER_ID).read_volatile() as usize >> 24 }; diff --git a/kernel/src/sys/mod.rs b/kernel/src/sys/mod.rs index 4edbffd..f72bf59 100644 --- a/kernel/src/sys/mod.rs +++ b/kernel/src/sys/mod.rs @@ -10,4 +10,5 @@ pub mod process; pub mod scheduler; pub mod smp; pub mod sync; +mod syscall; pub mod task; diff --git a/kernel/src/sys/syscall.rs b/kernel/src/sys/syscall.rs new file mode 100644 index 0000000..4de76fe --- /dev/null +++ b/kernel/src/sys/syscall.rs @@ -0,0 +1,2 @@ +#[no_mangle] +extern "C" fn syscall_handler() {} diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index 6ba5687..f18b56a 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -40,6 +40,7 @@ pub struct Task { pub sleep_until_us: usize, pub block_on_semaphore: Option>, pub semaphore_requested_count: usize, + user_stack: u64, } #[repr(C)] @@ -64,8 +65,10 @@ pub fn allocate_stack() -> u64 { pub fn switch_task(current_state: &mut ISRState, new_task: Task) { let lapic_id = get_current_lapic_id(); let mut current_tasks = CURRENT_TASKS.lock(); + let cpu_data = &mut CPUDATA.lock()[lapic_id]; if let Some(mut current_task) = current_tasks[lapic_id].take() { current_task.state = *current_state; + current_task.user_stack = cpu_data.user_stack; if current_task.task_state == TaskState::Terminated { unsafe { get_kernel_process().lock().address_space.switch(); @@ -90,7 +93,8 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { } } let kernel_stack = new_task.kernel_stack.as_ptr() as u64 + STACK_SIZE as u64; - CPUDATA.lock()[lapic_id].kernel_stack = kernel_stack; + cpu_data.kernel_stack = kernel_stack; + cpu_data.user_stack = new_task.user_stack; current_tasks[get_current_lapic_id()] = Some(new_task); schedule_timer_interrupt(); } @@ -100,6 +104,7 @@ pub fn create_task(process: Arc>, func: fn()) -> Task { id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst), process, state: ISRState { + ds: 0x10, rax: 0, rbx: 0, rcx: 0, @@ -129,6 +134,7 @@ pub fn create_task(process: Arc>, func: fn()) -> Task { sleep_until_us: 0, block_on_semaphore: None, semaphore_requested_count: 0, + user_stack: 0, } } fn create_idle_task() {