diff --git a/Cargo.toml b/Cargo.toml index 806b474..5d39115 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,6 @@ members = ["lib/acpica-rs", "lib/kernel-common", "loader", "kernel"] [profile.release] lto = true + +[profile.dev] +panic = "abort" diff --git a/build.sh b/build.sh index ba463fc..64ac156 100755 --- a/build.sh +++ b/build.sh @@ -1,15 +1,24 @@ #!/bin/bash set -euo pipefail +target=${OS_TARGET:-release} rm -rf img mkdir -p img/boot/efi/boot cd lib/acpica-build make -j4 cd ../../kernel -cargo build --release +if [ "$target" = "release" ]; then + cargo build --release +else + cargo build +fi cd ../loader -cargo build --release +if [ "$target" = "release" ]; then + cargo build --release +else + cargo build +fi cd .. -cp target/x86_64-unknown-uefi/release/loader.efi img/boot/efi/boot/bootx64.efi +cp target/x86_64-unknown-uefi/$target/loader.efi img/boot/efi/boot/bootx64.efi cd img dd if=/dev/zero of=boot.img bs=1M count=16 status=none mformat -i boot.img diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index a4afae0..e5bf4e5 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -15,3 +15,6 @@ hashbrown = "0.15.2" kernel-common = {path = "../lib/kernel-common"} log = "0.4.22" spin = "0.9.8" + +[lints.clippy] +missing_safety_doc = "allow" diff --git a/kernel/src/cpu/isr.rs b/kernel/src/cpu/isr.rs index ba5a81d..233ad47 100644 --- a/kernel/src/cpu/isr.rs +++ b/kernel/src/cpu/isr.rs @@ -9,7 +9,7 @@ use spin::Mutex; use crate::sys::{ lapic::{get_current_lapic_id, send_eoi}, scheduler::scheduler, - sync::{IN_ISR_HANDLER, LOCKS_HELD}, + sync::{Spinlock, IN_ISR_HANDLER, LOCKS_HELD}, }; global_asm!(include_str!("isr.s"), options(att_syntax)); @@ -79,6 +79,7 @@ const EXCEPTIONS: [&str; 32] = [ pub const ISR_INVALIDATE_TLB: u64 = 252; pub const ISR_SCHEDULER: u64 = 254; pub static ISR_HANDLERS: Mutex<[Option; 256]> = Mutex::new([None; 256]); +pub static ISR_HANDLERS_LOCK: Spinlock = Spinlock::new(); #[no_mangle] extern "C" fn isr_handler(state: &mut ISRState) { @@ -105,19 +106,21 @@ extern "C" fn isr_handler(state: &mut ISRState) { IN_ISR_HANDLER[lapic_id].store(true, Ordering::SeqCst); if state.isr == ISR_SCHEDULER { scheduler(state); - assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); + debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst); return; } let handler; { + ISR_HANDLERS_LOCK.lock(); handler = ISR_HANDLERS.lock()[state.isr as usize]; + ISR_HANDLERS_LOCK.unlock(); } if let Some(handler) = handler { handler(); } else { warn!("Unhandled interrupt: {}", state.isr); } - assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); + debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); IN_ISR_HANDLER[lapic_id].store(false, Ordering::SeqCst); } diff --git a/kernel/src/cpu/paging.rs b/kernel/src/cpu/paging.rs index d1e6f43..8532b3b 100644 --- a/kernel/src/cpu/paging.rs +++ b/kernel/src/cpu/paging.rs @@ -5,7 +5,7 @@ use core::{ }; use alloc::{boxed::Box, vec::Vec}; -use bitvec::{bitvec, order::Lsb0, vec::BitVec}; +use bitvec::{order::Lsb0, vec::BitVec}; use kernel_common::{ loader_struct::LoaderStruct, paging::{load_cr3, PageEntry, PageTable, KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START, KERNEL_VIRT_START}, @@ -191,7 +191,7 @@ pub unsafe fn unmap_physical(address: u64, size: u64) { pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) { HEAP_PHYS_START.store(heap_start, Ordering::SeqCst); let mut memory_size = 0; - for i in loader_struct.available_memory { + for i in &loader_struct.available_memory { if i.initial_page + i.page_count > memory_size { memory_size = i.initial_page + i.page_count; } @@ -199,9 +199,9 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u info!("Memory size: {} MB", memory_size * 0x1000 / 1024 / 1024); { let mut frames_vec = PHYSICAL_FRAMES.lock(); - *frames_vec = Some(bitvec![u64, Lsb0; 1; memory_size as usize]); + *frames_vec = Some(BitVec::::repeat(true, memory_size as usize)); let frames_vec = frames_vec.as_mut().unwrap(); - for i in loader_struct.available_memory { + for i in &loader_struct.available_memory { for j in 0..i.page_count { let page = i.initial_page + j; frames_vec.set(page as usize, false); diff --git a/kernel/src/cpu/trampoline.s b/kernel/src/cpu/trampoline.s index 65f8550..e1a079d 100644 --- a/kernel/src/cpu/trampoline.s +++ b/kernel/src/cpu/trampoline.s @@ -2,6 +2,7 @@ .code16 .align 0x1000 +.global ap_trampoline ap_trampoline: mov %cr4, %eax bts $5, %eax // Physical Address Extension @@ -29,10 +30,12 @@ ap_trampoline_2: call *%rax .align 4 +.global trampoline_pml4 trampoline_pml4: .int 0 .align 8 +.global trampoline_stack trampoline_stack: .quad 0 diff --git a/kernel/src/main.rs b/kernel/src/main.rs index f7f0c7f..bc0a0a1 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -30,7 +30,7 @@ use sys::{ early_acpi::EarlyACPIHandler, hpet::setup_hpet, lapic::{get_current_lapic_id, setup_lapic_timer, smp_broadcast_panic, start_aps}, - madt::parse_madt, + madt::{parse_madt, INTERRUPTS_SETUP}, pic::disable_pic, sync::LOCKS_HELD, task::setup_multitasking, @@ -108,8 +108,10 @@ fn main() { fn panic(info: &PanicInfo) -> ! { cli(); if !BROADCASTED_PANIC.load(Ordering::SeqCst) { - smp_broadcast_panic(); - LOCKS_HELD[get_current_lapic_id()].fetch_add(1, Ordering::SeqCst); + if INTERRUPTS_SETUP.load(Ordering::SeqCst) { + smp_broadcast_panic(); + LOCKS_HELD[get_current_lapic_id()].fetch_add(1, Ordering::SeqCst); + } error!("{}", info); let str = format!("{}", info); display_print(&str); diff --git a/kernel/src/misc/display.rs b/kernel/src/misc/display.rs index d09d6d9..fa88f8e 100644 --- a/kernel/src/misc/display.rs +++ b/kernel/src/misc/display.rs @@ -16,7 +16,7 @@ use spin::Mutex; use crate::{ cpu::paging::map_physical, misc::draw_target::FramebufferTarget, - sys::{sync::Spinlock, task::MULTITASKING_ENABLED}, + sys::{madt::INTERRUPTS_SETUP, sync::Spinlock}, }; static FRAMEBUFFER: Mutex> = Mutex::new(None); @@ -57,7 +57,7 @@ pub fn display_print(str: &str) { if FRAMEBUFFER_ADDR.load(Ordering::SeqCst) == null_mut() { return; } - if MULTITASKING_ENABLED.load(Ordering::SeqCst) { + if INTERRUPTS_SETUP.load(Ordering::SeqCst) { FRAMEBUFFER_LOCK.lock(); } let mut current_x = CURRENT_X.load(Ordering::SeqCst); @@ -84,7 +84,7 @@ pub fn display_print(str: &str) { CURRENT_X.store(current_x, Ordering::SeqCst); CURRENT_Y.store(current_y, Ordering::SeqCst); copy_to_fb(); - if MULTITASKING_ENABLED.load(Ordering::SeqCst) { + if INTERRUPTS_SETUP.load(Ordering::SeqCst) { FRAMEBUFFER_LOCK.unlock(); } } diff --git a/kernel/src/sys/ioapic.rs b/kernel/src/sys/ioapic.rs index 6d8905a..1e7f74a 100644 --- a/kernel/src/sys/ioapic.rs +++ b/kernel/src/sys/ioapic.rs @@ -6,7 +6,10 @@ use core::{ use bitfield::bitfield; use crate::{ - cpu::{isr::ISR_HANDLERS, paging::map_physical}, + cpu::{ + isr::{ISR_HANDLERS, ISR_HANDLERS_LOCK}, + paging::map_physical, + }, sys::lapic::BSP_LAPIC_ID, }; @@ -82,7 +85,11 @@ pub fn set_irq_override(gsi: usize, vector: usize, polarity: u8, trigger: u8) { } pub fn register_irq_handler(vector: usize, handler: fn()) { assert!(ISR_HANDLERS.lock()[vector].is_none()); - ISR_HANDLERS.lock()[vector] = Some(handler); + { + ISR_HANDLERS_LOCK.lock(); + ISR_HANDLERS.lock()[vector] = Some(handler); + ISR_HANDLERS_LOCK.unlock(); + } for i in 0..NEXT_IOAPIC_ID.load(Ordering::SeqCst) { let start = IOAPICS[i].start_gsi.load(Ordering::SeqCst); let end = IOAPICS[i].end_gsi.load(Ordering::SeqCst); diff --git a/kernel/src/sys/lapic.rs b/kernel/src/sys/lapic.rs index 128a360..8d2ef14 100644 --- a/kernel/src/sys/lapic.rs +++ b/kernel/src/sys/lapic.rs @@ -68,8 +68,7 @@ pub fn send_eoi() { pub fn get_current_lapic_id() -> usize { let address = ADDRESS.load(Ordering::SeqCst); let lapic_id = unsafe { address.add(REGISTER_ID).read_volatile() as usize >> 24 }; - let rflags = get_rflags(); - assert!(rflags & (1 << 9) == 0); + debug_assert!(get_rflags() & (1 << 9) == 0); lapic_id } pub fn setup_lapic(phys: u64) { diff --git a/kernel/src/sys/madt.rs b/kernel/src/sys/madt.rs index 33f5f7c..50e26b6 100644 --- a/kernel/src/sys/madt.rs +++ b/kernel/src/sys/madt.rs @@ -1,3 +1,5 @@ +use core::sync::atomic::{AtomicBool, Ordering}; + use acpi::{ madt::{Madt, MadtEntry}, AcpiTables, @@ -10,6 +12,8 @@ use super::{ lapic::{add_lapic, setup_lapic}, }; +pub static INTERRUPTS_SETUP: AtomicBool = AtomicBool::new(false); + pub fn parse_madt(tables: &AcpiTables) { let madt = tables.find_table::().unwrap(); let mut lapic_address: u64 = madt.local_apic_address as u64; @@ -42,4 +46,5 @@ pub fn parse_madt(tables: &AcpiTables) { unsafe { sti(); } + INTERRUPTS_SETUP.store(true, Ordering::SeqCst); } diff --git a/kernel/src/sys/scheduler.rs b/kernel/src/sys/scheduler.rs index 88c35e6..7fdcfea 100644 --- a/kernel/src/sys/scheduler.rs +++ b/kernel/src/sys/scheduler.rs @@ -1,17 +1,21 @@ use core::{arch::asm, sync::atomic::Ordering}; use alloc::{collections::vec_deque::VecDeque, vec::Vec}; -use kernel_common::instructions::cli; use spin::Mutex; use crate::cpu::isr::ISRState; use super::{ lapic::{get_current_lapic_id, schedule_timer_interrupt}, - sync::{Spinlock, IN_ISR_HANDLER, LOCKS_HELD}, + sync::Spinlock, task::{switch_task, Task, TaskState, CURRENT_TASKS, CURRENT_TASK_LOCK, MULTITASKING_ENABLED}, }; +#[cfg(debug_assertions)] +use super::sync::{IN_ISR_HANDLER, LOCKS_HELD}; +#[cfg(debug_assertions)] +use kernel_common::instructions::{cli, sti}; + static SCHEDULER_LIST: Mutex> = Mutex::new(VecDeque::new()); pub static IDLE_TASKS: Mutex> = Mutex::new(Vec::new()); pub static SCHEDULER_LOCK: Spinlock = Spinlock::new(); @@ -56,7 +60,7 @@ pub fn scheduler(state: &mut ISRState) { CURRENT_TASK_LOCK.unlock(); } pub fn schedule_task(task: Task) { - assert!(SCHEDULER_LOCK.is_locked() || !MULTITASKING_ENABLED.load(Ordering::SeqCst)); + debug_assert!(SCHEDULER_LOCK.is_locked() || !MULTITASKING_ENABLED.load(Ordering::SeqCst)); let mut scheduler_list = SCHEDULER_LIST.lock(); if scheduler_list.is_empty() { schedule_timer_interrupt(); @@ -64,11 +68,17 @@ pub fn schedule_task(task: Task) { scheduler_list.push_back(task); } pub fn yield_task() { - cli(); - let lapic_id = get_current_lapic_id(); - assert!(!IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst)); - assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); + #[cfg(debug_assertions)] + { + cli(); + let lapic_id = get_current_lapic_id(); + debug_assert!(!IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst)); + debug_assert_eq!(LOCKS_HELD[lapic_id].load(Ordering::SeqCst), 0); + unsafe { + sti(); + } + } unsafe { - asm!("sti; int $254"); + asm!("int $254"); } } diff --git a/kernel/src/sys/sync.rs b/kernel/src/sys/sync.rs index d0ef8c0..1aab843 100644 --- a/kernel/src/sys/sync.rs +++ b/kernel/src/sys/sync.rs @@ -4,7 +4,7 @@ use alloc::{collections::vec_deque::VecDeque, sync::Arc}; use kernel_common::instructions::{cli, sti}; use spin::Mutex; -use crate::sys::task::MULTITASKING_ENABLED; +use crate::sys::madt::INTERRUPTS_SETUP; use super::{ lapic::get_current_lapic_id, @@ -34,7 +34,7 @@ impl Spinlock { } } pub fn lock(&self) { - assert!(MULTITASKING_ENABLED.load(Ordering::SeqCst)); + debug_assert!(INTERRUPTS_SETUP.load(Ordering::SeqCst)); cli(); while !self.locked.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_ok() {} let lapic_id = get_current_lapic_id(); @@ -42,8 +42,9 @@ impl Spinlock { self.lapic_id.store(lapic_id, Ordering::SeqCst); } pub fn unlock(&self) { - assert!(self.locked.load(Ordering::SeqCst)); + debug_assert!(self.locked.load(Ordering::SeqCst)); let lapic_id = self.lapic_id.load(Ordering::SeqCst); + debug_assert_eq!(lapic_id, get_current_lapic_id()); self.locked.store(false, Ordering::SeqCst); LOCKS_HELD[lapic_id].fetch_sub(1, Ordering::SeqCst); if !IN_ISR_HANDLER[lapic_id].load(Ordering::SeqCst) && LOCKS_HELD[lapic_id].load(Ordering::SeqCst) == 0 { @@ -109,7 +110,7 @@ pub fn unlock_semaphore(semaphore: Arc, count: usize) { semaphore.spinlock.lock(); { semaphore.current_count.fetch_add(count, Ordering::SeqCst); - assert!(semaphore.current_count.load(Ordering::SeqCst) <= semaphore.max_count); + debug_assert!(semaphore.current_count.load(Ordering::SeqCst) <= semaphore.max_count); while let Some(mut task) = semaphore.blocked_list.lock().pop_front() { task.block_on_semaphore = None; task.semaphore_requested_count = 0; diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index fd48f5c..6fdd36f 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -55,7 +55,7 @@ pub fn allocate_stack() -> u64 { stack.leak().as_mut_ptr() as u64 + STACK_SIZE as u64 } pub fn switch_task(current_state: &mut ISRState, new_task: Task) { - assert!(CURRENT_TASK_LOCK.is_locked()); + debug_assert!(CURRENT_TASK_LOCK.is_locked()); let mut _current_task = CURRENT_TASKS.lock(); if let Some(mut current_task) = _current_task.remove(&get_current_lapic_id()) { current_task.state = *current_state; diff --git a/lib/kernel-common/Cargo.toml b/lib/kernel-common/Cargo.toml index 9231b39..ea0774b 100644 --- a/lib/kernel-common/Cargo.toml +++ b/lib/kernel-common/Cargo.toml @@ -7,3 +7,6 @@ license = "Unlicense" [dependencies] bitfield = "0.17.0" log = "0.4.22" + +[lints.clippy] +missing_safety_doc = "allow" diff --git a/loader/Cargo.toml b/loader/Cargo.toml index 733e6ac..33baddc 100644 --- a/loader/Cargo.toml +++ b/loader/Cargo.toml @@ -11,3 +11,6 @@ log = "0.4.22" raw-cpuid = "11.2.0" static-alloc = "0.2.5" uefi = "0.33.0" + +[lints.clippy] +missing_safety_doc = "allow" diff --git a/loader/src/main.rs b/loader/src/main.rs index ebaeb44..2f53c71 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -39,6 +39,10 @@ mod paging; static ALLOC: Bump<[u8; 8 * 1024 * 1024]> = Bump::uninit(); static BOOT_SERVICES_ACTIVE: AtomicBool = AtomicBool::new(false); +#[cfg(debug_assertions)] +const KERNEL: &[u8] = include_bytes!("../../target/x86_64-unknown-none/debug/kernel"); + +#[cfg(not(debug_assertions))] const KERNEL: &[u8] = include_bytes!("../../target/x86_64-unknown-none/release/kernel"); #[entry]