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::{
|
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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -2,4 +2,8 @@
|
||||||
|
|
||||||
.global syscall
|
.global syscall
|
||||||
syscall:
|
syscall:
|
||||||
|
swapgs
|
||||||
|
mov %rsp, %gs:8
|
||||||
|
mov %gs:0, %rsp
|
||||||
|
swapgs
|
||||||
jmp .
|
jmp .
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue