This commit is contained in:
parent
25693bb57c
commit
1cccf16bfe
6 changed files with 38 additions and 17 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2,4 +2,8 @@
|
|||
|
||||
.global syscall
|
||||
syscall:
|
||||
swapgs
|
||||
mov %rsp, %gs:8
|
||||
mov %gs:0, %rsp
|
||||
swapgs
|
||||
jmp .
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct Task {
|
|||
pub id: usize,
|
||||
pub process: Arc<Spinlock<Process>>,
|
||||
state: ISRState,
|
||||
_kernel_stack: Vec<u8>,
|
||||
kernel_stack: Vec<u8>,
|
||||
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<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 STARTING_AP_ID: AtomicI64 = AtomicI64::new(-1);
|
||||
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 {
|
||||
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();
|
||||
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<Spinlock<Process>>, 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue