From 1cccf16bfe8140db8eb0d5ff6feb031d8be046d9 Mon Sep 17 00:00:00 2001 From: Mathieu Strypsteen Date: Sun, 22 Dec 2024 21:24:08 +0100 Subject: [PATCH] More syscall preparation --- kernel/src/cpu/cpu.rs | 7 ++++++- kernel/src/cpu/gdt.rs | 1 + kernel/src/cpu/idt.rs | 3 +++ kernel/src/cpu/isr.rs | 10 ++++++---- kernel/src/cpu/syscall.s | 4 ++++ kernel/src/sys/task.rs | 30 ++++++++++++++++++------------ 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/kernel/src/cpu/cpu.rs b/kernel/src/cpu/cpu.rs index 8b86eaf..738c4f5 100644 --- a/kernel/src/cpu/cpu.rs +++ b/kernel/src/cpu/cpu.rs @@ -6,8 +6,9 @@ use raw_cpuid::CpuId; use crate::{ cpu::{gdt::setup_gdt, idt::setup_idt}, sys::{ - lapic::{setup_lapic, setup_lapic_timer}, + lapic::{get_current_lapic_id, setup_lapic, setup_lapic_timer}, scheduler::yield_task, + task::{CPUData, CPUDATA}, }, }; @@ -51,6 +52,10 @@ pub fn set_cpu_flags() { // Clear IF and DF asm!("wrmsr", in("rcx") 0xc0000084_u64, in("rax") 1 << 9 | 1 << 10, in("rdx") 0); } + let cpudata_address = &CPUDATA.lock()[get_current_lapic_id()] as *const CPUData as u64; + unsafe { + asm!("wrmsr", in("rcx") 0xc0000102_u64, in("rax") cpudata_address, in("rdx") cpudata_address >> 32); + } } pub fn enable_user_memory_access() { unsafe { diff --git a/kernel/src/cpu/gdt.rs b/kernel/src/cpu/gdt.rs index 8d86f73..02fd9ed 100644 --- a/kernel/src/cpu/gdt.rs +++ b/kernel/src/cpu/gdt.rs @@ -59,6 +59,7 @@ pub fn setup_gdt() { tss.ist[0] = allocate_stack(); tss.ist[1] = allocate_stack(); tss.ist[2] = allocate_stack(); + tss.ist[3] = allocate_stack(); let gdt = Box::leak(Box::new(GDT { entries: [ GDTEntry { diff --git a/kernel/src/cpu/idt.rs b/kernel/src/cpu/idt.rs index 91c1a30..65b4e58 100644 --- a/kernel/src/cpu/idt.rs +++ b/kernel/src/cpu/idt.rs @@ -2,6 +2,8 @@ use core::{arch::asm, mem::size_of}; use alloc::boxed::Box; +use super::isr::ISR_SCHEDULER; + #[repr(C)] #[derive(Clone, Copy)] struct IDTEntry { @@ -326,4 +328,5 @@ pub fn setup_idt() { idt.entries[2].ist = 1; // NMI idt.entries[8].ist = 2; // Double fault idt.entries[18].ist = 3; // Machine Check + idt.entries[ISR_SCHEDULER as usize].ist = 4; } diff --git a/kernel/src/cpu/isr.rs b/kernel/src/cpu/isr.rs index 0137d96..dd1d5ca 100644 --- a/kernel/src/cpu/isr.rs +++ b/kernel/src/cpu/isr.rs @@ -12,7 +12,7 @@ use crate::{ locks::Spinlock, scheduler::scheduler, sync::{IN_ISR_HANDLER, LOCKS_HELD}, - task::{terminate_current_task, terminate_tasks}, + task::terminate_current_task, }, BROADCASTED_PANIC, }; @@ -114,12 +114,14 @@ extern "C" fn isr_handler(state: &mut ISRState) { if state.cs == 0x23 && state.isr != 2 && state.isr != 8 && state.isr != 18 { warn!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]); terminate_current_task(); - state.isr = ISR_SCHEDULER; + IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst); + unsafe { + asm!("int $254"); + } + panic!("Failed to terminate task"); } else { panic!("Exception: {}", EXCEPTIONS[state.isr as usize]); } - } else { - terminate_tasks(); } if state.isr == ISR_SCHEDULER { scheduler(state); diff --git a/kernel/src/cpu/syscall.s b/kernel/src/cpu/syscall.s index d8f7e48..7618096 100644 --- a/kernel/src/cpu/syscall.s +++ b/kernel/src/cpu/syscall.s @@ -2,4 +2,8 @@ .global syscall syscall: + swapgs + mov %rsp, %gs:8 + mov %gs:0, %rsp + swapgs jmp . diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index 561621d..6ba5687 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -34,7 +34,7 @@ pub struct Task { pub id: usize, pub process: Arc>, state: ISRState, - _kernel_stack: Vec, + kernel_stack: Vec, initial_func: fn(), pub task_state: TaskState, pub sleep_until_us: usize, @@ -42,6 +42,12 @@ pub struct Task { pub semaphore_requested_count: usize, } +#[repr(C)] +pub struct CPUData { + pub kernel_stack: u64, + pub user_stack: u64, +} + pub const STACK_SIZE: usize = 64 * 1024; static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2); pub static CURRENT_TASKS: Spinlock<[Option; 256]> = Spinlock::new([const { None }; 256]); @@ -49,7 +55,7 @@ static RFLAGS: AtomicU64 = AtomicU64::new(0); pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false); pub static STARTING_AP_ID: AtomicI64 = AtomicI64::new(-1); pub static ALL_APS_STARTED: AtomicBool = AtomicBool::new(false); -pub static TERMINATE_STASKS: [Spinlock>; 256] = [const { Spinlock::new(Vec::new()) }; 256]; +pub static CPUDATA: Spinlock<[CPUData; 256]> = Spinlock::new([const { CPUData { kernel_stack: 0, user_stack: 0 } }; 256]); pub fn allocate_stack() -> u64 { let stack: Vec = vec![0; STACK_SIZE]; @@ -60,14 +66,17 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { let mut current_tasks = CURRENT_TASKS.lock(); if let Some(mut current_task) = current_tasks[lapic_id].take() { current_task.state = *current_state; + if current_task.task_state == TaskState::Terminated { + unsafe { + get_kernel_process().lock().address_space.switch(); + } + } match current_task.task_state { TaskState::Ready => { SCHEDULER.lock().add_task(current_task); } TaskState::Idle => IDLE_TASKS.lock().push(current_task), - TaskState::Terminated => { - TERMINATE_STASKS[lapic_id].lock().push(current_task); - } + TaskState::Terminated => {} TaskState::Sleeping => sleep_internal(current_task), TaskState::SemaphoreBlocked => lock_semaphore_internal(current_task), } @@ -80,6 +89,8 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { process.address_space.switch(); } } + let kernel_stack = new_task.kernel_stack.as_ptr() as u64 + STACK_SIZE as u64; + CPUDATA.lock()[lapic_id].kernel_stack = kernel_stack; current_tasks[get_current_lapic_id()] = Some(new_task); schedule_timer_interrupt(); } @@ -112,7 +123,7 @@ pub fn create_task(process: Arc>, func: fn()) -> Task { rsp: stack.as_ptr() as u64 + STACK_SIZE as u64, ss: 16, }, - _kernel_stack: stack, + kernel_stack: stack, initial_func: func, task_state: TaskState::Ready, sleep_until_us: 0, @@ -138,9 +149,7 @@ extern "C" fn task_entry() -> ! { func = task[get_current_lapic_id()].as_ref().unwrap().initial_func; } func(); - { - terminate_current_task(); - } + terminate_current_task(); yield_task(); panic!("Failed to terminate task"); } @@ -159,9 +168,6 @@ fn idle_main() { hlt(); } } -pub fn terminate_tasks() { - TERMINATE_STASKS[get_current_lapic_id()].lock().clear(); -} pub fn setup_multitasking() -> ! { let rflags = get_rflags(); RFLAGS.store(rflags, core::sync::atomic::Ordering::SeqCst);