More syscall preparation
All checks were successful
Build / build (push) Successful in 2m52s

This commit is contained in:
Mathieu Strypsteen 2024-12-22 21:24:08 +01:00
parent 25693bb57c
commit 1cccf16bfe
6 changed files with 38 additions and 17 deletions

View file

@ -6,8 +6,9 @@ use raw_cpuid::CpuId;
use crate::{ use crate::{
cpu::{gdt::setup_gdt, idt::setup_idt}, cpu::{gdt::setup_gdt, idt::setup_idt},
sys::{ sys::{
lapic::{setup_lapic, setup_lapic_timer}, lapic::{get_current_lapic_id, setup_lapic, setup_lapic_timer},
scheduler::yield_task, scheduler::yield_task,
task::{CPUData, CPUDATA},
}, },
}; };
@ -51,6 +52,10 @@ pub fn set_cpu_flags() {
// Clear IF and DF // Clear IF and DF
asm!("wrmsr", in("rcx") 0xc0000084_u64, in("rax") 1 << 9 | 1 << 10, in("rdx") 0); 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() { pub fn enable_user_memory_access() {
unsafe { unsafe {

View file

@ -59,6 +59,7 @@ pub fn setup_gdt() {
tss.ist[0] = allocate_stack(); tss.ist[0] = allocate_stack();
tss.ist[1] = allocate_stack(); tss.ist[1] = allocate_stack();
tss.ist[2] = allocate_stack(); tss.ist[2] = allocate_stack();
tss.ist[3] = allocate_stack();
let gdt = Box::leak(Box::new(GDT { let gdt = Box::leak(Box::new(GDT {
entries: [ entries: [
GDTEntry { GDTEntry {

View file

@ -2,6 +2,8 @@ use core::{arch::asm, mem::size_of};
use alloc::boxed::Box; use alloc::boxed::Box;
use super::isr::ISR_SCHEDULER;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct IDTEntry { struct IDTEntry {
@ -326,4 +328,5 @@ pub fn setup_idt() {
idt.entries[2].ist = 1; // NMI idt.entries[2].ist = 1; // NMI
idt.entries[8].ist = 2; // Double fault idt.entries[8].ist = 2; // Double fault
idt.entries[18].ist = 3; // Machine Check idt.entries[18].ist = 3; // Machine Check
idt.entries[ISR_SCHEDULER as usize].ist = 4;
} }

View file

@ -12,7 +12,7 @@ use crate::{
locks::Spinlock, locks::Spinlock,
scheduler::scheduler, scheduler::scheduler,
sync::{IN_ISR_HANDLER, LOCKS_HELD}, sync::{IN_ISR_HANDLER, LOCKS_HELD},
task::{terminate_current_task, terminate_tasks}, task::terminate_current_task,
}, },
BROADCASTED_PANIC, 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 { if state.cs == 0x23 && state.isr != 2 && state.isr != 8 && state.isr != 18 {
warn!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]); warn!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]);
terminate_current_task(); 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 { } else {
panic!("Exception: {}", EXCEPTIONS[state.isr as usize]); panic!("Exception: {}", EXCEPTIONS[state.isr as usize]);
} }
} else {
terminate_tasks();
} }
if state.isr == ISR_SCHEDULER { if state.isr == ISR_SCHEDULER {
scheduler(state); scheduler(state);

View file

@ -2,4 +2,8 @@
.global syscall .global syscall
syscall: syscall:
swapgs
mov %rsp, %gs:8
mov %gs:0, %rsp
swapgs
jmp . jmp .

View file

@ -34,7 +34,7 @@ pub struct Task {
pub id: usize, pub id: usize,
pub process: Arc<Spinlock<Process>>, pub process: Arc<Spinlock<Process>>,
state: ISRState, state: ISRState,
_kernel_stack: Vec<u8>, kernel_stack: Vec<u8>,
initial_func: fn(), initial_func: fn(),
pub task_state: TaskState, pub task_state: TaskState,
pub sleep_until_us: usize, pub sleep_until_us: usize,
@ -42,6 +42,12 @@ pub struct Task {
pub semaphore_requested_count: usize, 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; pub const STACK_SIZE: usize = 64 * 1024;
static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2); static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2);
pub static CURRENT_TASKS: Spinlock<[Option<Task>; 256]> = Spinlock::new([const { None }; 256]); pub static CURRENT_TASKS: Spinlock<[Option<Task>; 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 MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false);
pub static STARTING_AP_ID: AtomicI64 = AtomicI64::new(-1); pub static STARTING_AP_ID: AtomicI64 = AtomicI64::new(-1);
pub static ALL_APS_STARTED: AtomicBool = AtomicBool::new(false); pub static ALL_APS_STARTED: AtomicBool = AtomicBool::new(false);
pub static TERMINATE_STASKS: [Spinlock<Vec<Task>>; 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 { pub fn allocate_stack() -> u64 {
let stack: Vec<u8> = vec![0; STACK_SIZE]; let stack: Vec<u8> = 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(); let mut current_tasks = CURRENT_TASKS.lock();
if let Some(mut current_task) = current_tasks[lapic_id].take() { if let Some(mut current_task) = current_tasks[lapic_id].take() {
current_task.state = *current_state; 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 { match current_task.task_state {
TaskState::Ready => { TaskState::Ready => {
SCHEDULER.lock().add_task(current_task); SCHEDULER.lock().add_task(current_task);
} }
TaskState::Idle => IDLE_TASKS.lock().push(current_task), TaskState::Idle => IDLE_TASKS.lock().push(current_task),
TaskState::Terminated => { TaskState::Terminated => {}
TERMINATE_STASKS[lapic_id].lock().push(current_task);
}
TaskState::Sleeping => sleep_internal(current_task), TaskState::Sleeping => sleep_internal(current_task),
TaskState::SemaphoreBlocked => lock_semaphore_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(); 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); current_tasks[get_current_lapic_id()] = Some(new_task);
schedule_timer_interrupt(); schedule_timer_interrupt();
} }
@ -112,7 +123,7 @@ pub fn create_task(process: Arc<Spinlock<Process>>, func: fn()) -> Task {
rsp: stack.as_ptr() as u64 + STACK_SIZE as u64, rsp: stack.as_ptr() as u64 + STACK_SIZE as u64,
ss: 16, ss: 16,
}, },
_kernel_stack: stack, kernel_stack: stack,
initial_func: func, initial_func: func,
task_state: TaskState::Ready, task_state: TaskState::Ready,
sleep_until_us: 0, 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 = task[get_current_lapic_id()].as_ref().unwrap().initial_func;
} }
func(); func();
{ terminate_current_task();
terminate_current_task();
}
yield_task(); yield_task();
panic!("Failed to terminate task"); panic!("Failed to terminate task");
} }
@ -159,9 +168,6 @@ fn idle_main() {
hlt(); hlt();
} }
} }
pub fn terminate_tasks() {
TERMINATE_STASKS[get_current_lapic_id()].lock().clear();
}
pub fn setup_multitasking() -> ! { pub fn setup_multitasking() -> ! {
let rflags = get_rflags(); let rflags = get_rflags();
RFLAGS.store(rflags, core::sync::atomic::Ordering::SeqCst); RFLAGS.store(rflags, core::sync::atomic::Ordering::SeqCst);