This commit is contained in:
parent
5b491989da
commit
2e4460ace6
10 changed files with 113 additions and 38 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -64,7 +64,7 @@ dependencies = [
|
|||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.90",
|
||||
"syn 2.0.91",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -319,7 +319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.90",
|
||||
"syn 2.0.91",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -453,9 +453,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
version = "2.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -501,7 +501,7 @@ checksum = "9b24e77d3fc1e617051e630f99da24bcae6328abab37b8f9216bb68d06804f9a"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.90",
|
||||
"syn 2.0.91",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
use core::{arch::global_asm, panic::PanicInfo};
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
global_asm!(include_str!("start.s"), options(att_syntax));
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn _start() -> ! {
|
||||
extern "C" fn main() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
|
|
11
init/src/start.s
Normal file
11
init/src/start.s
Normal file
|
@ -0,0 +1,11 @@
|
|||
.text
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
mov $stack, %rsp
|
||||
call main
|
||||
|
||||
.section .bss
|
||||
.align 16
|
||||
.skip 0x10000
|
||||
stack:
|
|
@ -55,6 +55,7 @@ pub fn setup_gdt() {
|
|||
reserved4: 0,
|
||||
iopb_offset: size_of::<TSS>() as u16,
|
||||
}));
|
||||
tss.rsp[0] = allocate_stack();
|
||||
tss.ist[0] = allocate_stack();
|
||||
tss.ist[1] = allocate_stack();
|
||||
let gdt = Box::leak(Box::new(GDT {
|
||||
|
@ -113,7 +114,7 @@ pub fn setup_gdt() {
|
|||
}));
|
||||
let gdt_descriptor = Box::leak(Box::new(GDTDescriptor {
|
||||
limit: (size_of::<GDT>() - 1) as u16,
|
||||
base: gdt.entries.as_ptr() as u64,
|
||||
base: gdt as *mut GDT as u64,
|
||||
}));
|
||||
unsafe {
|
||||
asm!("
|
||||
|
|
|
@ -3,13 +3,18 @@ use core::{
|
|||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
use kernel_common::instructions::hlt;
|
||||
use log::warn;
|
||||
|
||||
use crate::sys::{
|
||||
use crate::{
|
||||
sys::{
|
||||
lapic::{get_current_lapic_id, send_eoi},
|
||||
locks::Spinlock,
|
||||
scheduler::scheduler,
|
||||
sync::{IN_ISR_HANDLER, LOCKS_HELD},
|
||||
task::{terminate_current_task, terminate_tasks},
|
||||
},
|
||||
BROADCASTED_PANIC,
|
||||
};
|
||||
|
||||
global_asm!(include_str!("isr.s"), options(att_syntax));
|
||||
|
@ -82,8 +87,10 @@ pub static ISR_HANDLERS: Spinlock<[Option<fn()>; 256]> = Spinlock::new([None; 25
|
|||
|
||||
#[no_mangle]
|
||||
extern "C" fn isr_handler(state: &mut ISRState) {
|
||||
if state.isr < 32 {
|
||||
panic!("Exception: {}", EXCEPTIONS[state.isr as usize]);
|
||||
if BROADCASTED_PANIC.load(Ordering::SeqCst) {
|
||||
loop {
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
if 32 <= state.isr && state.isr <= 47 {
|
||||
return; // Legacy PIC interrupt
|
||||
|
@ -103,6 +110,17 @@ extern "C" fn isr_handler(state: &mut ISRState) {
|
|||
}
|
||||
let lapic_id = get_current_lapic_id();
|
||||
IN_ISR_HANDLER[lapic_id].store(true, Ordering::SeqCst);
|
||||
if state.isr < 32 {
|
||||
if state.cs == 0x1b && state.isr != 2 && state.isr != 8 {
|
||||
warn!("Exception in usermode: {}", EXCEPTIONS[state.isr as usize]);
|
||||
terminate_current_task();
|
||||
state.isr = ISR_SCHEDULER;
|
||||
} else {
|
||||
panic!("Exception: {}", EXCEPTIONS[state.isr as usize]);
|
||||
}
|
||||
} else {
|
||||
terminate_tasks();
|
||||
}
|
||||
if state.isr == ISR_SCHEDULER {
|
||||
scheduler(state);
|
||||
debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0);
|
||||
|
|
31
kernel/src/cpu/usermode.s
Normal file
31
kernel/src/cpu/usermode.s
Normal file
|
@ -0,0 +1,31 @@
|
|||
.text
|
||||
|
||||
.global jump_usermode
|
||||
jump_usermode:
|
||||
mov $0x23, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
push $0x23
|
||||
push $0
|
||||
pushf
|
||||
push $0x1b
|
||||
push %rdi
|
||||
|
||||
xor %rax, %rax
|
||||
xor %rbx, %rbx
|
||||
xor %rcx, %rcx
|
||||
xor %rdx, %rdx
|
||||
xor %rdi, %rdi
|
||||
xor %rsi, %rsi
|
||||
xor %rbp, %rbp
|
||||
xor %r8, %r8
|
||||
xor %r9, %r9
|
||||
xor %r10, %r10
|
||||
xor %r11, %r11
|
||||
xor %r12, %r12
|
||||
xor %r13, %r13
|
||||
xor %r14, %r14
|
||||
xor %r15, %r15
|
||||
iretq
|
|
@ -63,6 +63,7 @@ pub static BROADCASTED_PANIC: AtomicBool = AtomicBool::new(false);
|
|||
|
||||
global_asm!(include_str!("cpu/boot.s"), options(att_syntax));
|
||||
global_asm!(include_str!("cpu/trampoline.s"), options(att_syntax));
|
||||
global_asm!(include_str!("cpu/usermode.s"), options(att_syntax));
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const INIT_BINARY: &[u8] = include_bytes!("../../target/x86_64-unknown-none/debug/init");
|
||||
|
@ -116,10 +117,9 @@ fn main() {
|
|||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
cli();
|
||||
if !BROADCASTED_PANIC.load(Ordering::SeqCst) {
|
||||
if INTERRUPTS_SETUP.load(Ordering::SeqCst) {
|
||||
smp_broadcast_panic();
|
||||
LOCKS_HELD[get_current_lapic_id()].fetch_add(1, Ordering::SeqCst);
|
||||
smp_broadcast_panic();
|
||||
}
|
||||
error!("{}", info);
|
||||
let str = format!("{}", info);
|
||||
|
@ -128,7 +128,6 @@ fn panic(info: &PanicInfo) -> ! {
|
|||
display.clear();
|
||||
display.print(&str);
|
||||
}
|
||||
}
|
||||
loop {
|
||||
hlt();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use core::{mem, ptr};
|
||||
use core::ptr;
|
||||
|
||||
use elf::{abi::PT_LOAD, endian::LittleEndian, ElfBytes};
|
||||
use log::info;
|
||||
|
@ -8,10 +8,13 @@ use crate::{
|
|||
sys::{lapic::get_current_lapic_id, task::CURRENT_TASKS},
|
||||
};
|
||||
|
||||
const USER_END: u64 = 0x800000000000;
|
||||
const USER_END: u64 = 0x800000000000 - 0x1000; // Avoid accidentally jumping to non-canonical address
|
||||
|
||||
extern "C" {
|
||||
fn jump_usermode(address: u64) -> !;
|
||||
}
|
||||
|
||||
// TODO: Proper error handling
|
||||
// TODO: Verify whether p_offset is within bounds
|
||||
pub fn load_binary() {
|
||||
let process;
|
||||
{
|
||||
|
@ -30,10 +33,11 @@ pub fn load_binary() {
|
|||
}
|
||||
let write = i.p_flags & 2 != 0;
|
||||
let exec = i.p_flags & 1 != 0;
|
||||
assert!(i.p_vaddr < USER_END);
|
||||
assert!(i.p_vaddr + i.p_memsz < USER_END);
|
||||
assert!(i.p_vaddr + i.p_memsz >= i.p_vaddr);
|
||||
assert!(i.p_filesz <= i.p_memsz);
|
||||
assert!(i.p_offset + i.p_filesz <= binary.len() as u64);
|
||||
assert!(i.p_offset + i.p_filesz >= i.p_offset);
|
||||
assert!(!write || !exec);
|
||||
let start = i.p_vaddr / 0x1000 * 0x1000;
|
||||
let end = (i.p_vaddr + i.p_memsz + 0xfff) / 0x1000 * 0x1000;
|
||||
|
@ -48,14 +52,14 @@ pub fn load_binary() {
|
|||
}
|
||||
disable_user_memory_access();
|
||||
unsafe {
|
||||
// TODO: enable user flag
|
||||
process.address_space.update_flags_range(start, size, false, write, exec);
|
||||
process.address_space.update_flags_range(start, size, true, write, exec);
|
||||
}
|
||||
}
|
||||
entry = file.ehdr.e_entry;
|
||||
assert!(entry < USER_END);
|
||||
}
|
||||
info!("Starting init...");
|
||||
unsafe {
|
||||
(mem::transmute::<u64, extern "C" fn() -> !>(entry))();
|
||||
jump_usermode(entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,21 +49,25 @@ 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 fn allocate_stack() -> u64 {
|
||||
let stack: Vec<u8> = vec![0; STACK_SIZE];
|
||||
stack.leak().as_mut_ptr() as u64 + STACK_SIZE as 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();
|
||||
if let Some(mut current_task) = current_tasks[get_current_lapic_id()].take() {
|
||||
if let Some(mut current_task) = current_tasks[lapic_id].take() {
|
||||
current_task.state = *current_state;
|
||||
match current_task.task_state {
|
||||
TaskState::Ready => {
|
||||
SCHEDULER.lock().add_task(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::SemaphoreBlocked => lock_semaphore_internal(current_task),
|
||||
}
|
||||
|
@ -124,6 +128,9 @@ fn create_idle_task() {
|
|||
IDLE_TASKS.lock().push(idle_task);
|
||||
}
|
||||
}
|
||||
pub fn terminate_current_task() {
|
||||
CURRENT_TASKS.lock()[get_current_lapic_id()].as_mut().unwrap().task_state = TaskState::Terminated;
|
||||
}
|
||||
extern "C" fn task_entry() -> ! {
|
||||
let func;
|
||||
{
|
||||
|
@ -132,7 +139,7 @@ extern "C" fn task_entry() -> ! {
|
|||
}
|
||||
func();
|
||||
{
|
||||
CURRENT_TASKS.lock()[get_current_lapic_id()].as_mut().unwrap().task_state = TaskState::Terminated;
|
||||
terminate_current_task();
|
||||
}
|
||||
yield_task();
|
||||
panic!("Failed to terminate task");
|
||||
|
@ -152,6 +159,9 @@ 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);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 437f7e1a0039d227d3952677c3f9f5ad9c814395
|
||||
Subproject commit 7dae72155bf06b0edda9f3aea713da1d48c1c418
|
Loading…
Add table
Reference in a new issue