diff --git a/Cargo.toml b/Cargo.toml index f801226..994daaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,6 @@ humansize = "2.1.3" cast = "0.3.0" az = "1.2.1" unsigned-varint = "0.8.0" + +[features] +log-rpc = [] diff --git a/src/interrupts.rs b/src/interrupts.rs index f487974..5d7993f 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -1,7 +1,6 @@ use crate::{ bootinfo::BOOTINFO, print, println, - serial::SECOND_PORT, tasking::SleepReason, virtual_memory::{ASpaceMutex, AddressSpace, ACTIVE_SPACE, KERNEL_SPACE}, TASKING, @@ -11,16 +10,12 @@ use az::WrappingCast; use cast::{u64, usize}; use core::{ arch::{asm, naked_asm}, - ffi::CStr, - fmt::Write, ptr, slice, }; use hashbrown::HashMap; use pic8259::ChainedPics; -use saturating_cast::SaturatingCast; use spin::{Lazy, Mutex, RwLock}; use x86_64::{ - instructions::port::{Port, PortReadOnly}, registers::control::Cr2, set_general_handler, structures::{ @@ -32,6 +27,11 @@ use x86_64::{ PhysAddr, PrivilegeLevel, VirtAddr, }; +#[cfg(feature = "log-rpc")] +use crate::serial::SECOND_PORT; +#[cfg(feature = "log-rpc")] +use saturating_cast::SaturatingCast; + const IRQ_BASE: u8 = 32; static IDT: Lazy = Lazy::new(|| { @@ -110,7 +110,6 @@ fn general_handler(stack_frame: InterruptStackFrame, index: u8, _error_code: Opt println!("Other interrupt {index}\n{stack_frame:#?}"); } -#[expect(clippy::needless_pass_by_value, reason = "Signature dictated by external crate")] fn exc_handler(_stack_frame: InterruptStackFrame, _index: u8, _error_code: Option) { if let Some(current_pid) = TASKING.current_pid() { print!("PID {current_pid} "); @@ -132,44 +131,47 @@ impl Drop for EoiGuard { } pub fn send_ipc_to(pid: usize, buffer: Box<[u8], &'static ASpaceMutex>, len: usize) { - //#[expect( - // clippy::unwrap_used, - // reason = "The min call guarantees that the value is in the range of a u32 before the cast" - //)] - //let trunc_len: u32 = usize::min(len, 4096).try_into().unwrap(); - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't underflow, as x % 4 < 4 no matter the x" - //)] - //let padding = if (trunc_len % 4) != 0 { 4 - (trunc_len % 4) } else { 0 }; - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't overflow, as padding is no more than 4 and trunc_len is no more than 4096." - //)] - //let padded_len = trunc_len + padding; - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX" - //)] - //let total_len = padded_len + 8 + (4 * 4); - //SECOND_PORT.write_u32s(&[ - // 0x3, // SPB type - // total_len, // Total block length - // len.saturating_cast::().saturating_add(8), // Packet length - //]); - //SECOND_PORT.write_bytes(&pid.to_ne_bytes()); - //#[expect( - // clippy::indexing_slicing, - // reason = "The truncated length is always <= the buffer's length" - //)] - //SECOND_PORT.write_bytes(&buffer[0..usize(trunc_len)]); - //for _ in 0..padding { - // SECOND_PORT.write_bytes(&[0]); - //} - //SECOND_PORT.write_u32s(&[ - // total_len, // Total block length - //]); - //assert!(len <= buffer.len()); + #[cfg(feature = "log-rpc")] + { + #[expect( + clippy::unwrap_used, + reason = "The min call guarantees that the value is in the range of a u32 before the cast" + )] + let trunc_len: u32 = usize::min(len, 4096).try_into().unwrap(); + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't underflow, as x % 4 < 4 no matter the x" + )] + let padding = if (trunc_len % 4) != 0 { 4 - (trunc_len % 4) } else { 0 }; + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't overflow, as padding is no more than 4 and trunc_len is no more than 4096." + )] + let padded_len = trunc_len + padding; + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX" + )] + let total_len = padded_len + 8 + (4 * 4); + SECOND_PORT.write_u32s(&[ + 0x3, // SPB type + total_len, // Total block length + len.saturating_cast::().saturating_add(8), // Packet length + ]); + SECOND_PORT.write_bytes(&pid.to_ne_bytes()); + #[expect( + clippy::indexing_slicing, + reason = "The truncated length is always <= the buffer's length" + )] + SECOND_PORT.write_bytes(&buffer[0..usize(trunc_len)]); + for _ in 0..padding { + SECOND_PORT.write_bytes(&[0]); + } + SECOND_PORT.write_u32s(&[ + total_len, // Total block length + ]); + } + assert!(len <= buffer.len()); if TASKING.message_queue_mut(pid, |_| ()).is_ok() { let buf_num_pages = buffer.len() / 4096; let buffer = Box::into_raw(buffer); @@ -209,7 +211,6 @@ pub fn send_ipc_to(pid: usize, buffer: Box<[u8], &'static ASpaceMutex>, len: usi } } -#[expect(clippy::needless_pass_by_value, reason = "Signature dictated by external crate")] fn irq_handler(_stack_frame: InterruptStackFrame, index: u8, _error_code: Option) { #[expect( clippy::arithmetic_side_effects, @@ -500,43 +501,46 @@ extern "C" fn syscall_handler() { let len = usize(regs.rsi); assert!(len <= buffer.len()); if TASKING.message_queue_mut(pid, |_| ()).is_ok() { - //#[expect( - // clippy::unwrap_used, - // reason = "The min call guarantees that the value is in the range of a u32 before the cast" - //)] - //let trunc_len: u32 = usize::min(len, 4096).try_into().unwrap(); - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't underflow, as x % 4 < 4 no matter the x" - //)] - //let padding = if (trunc_len % 4) != 0 { 4 - (trunc_len % 4) } else { 0 }; - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't overflow, as padding is no more than 4 and trunc_len is no more than 4096." - //)] - //let padded_len = trunc_len + padding; - //#[expect( - // clippy::arithmetic_side_effects, - // reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX" - //)] - //let total_len = padded_len + 8 + (4 * 4); - //SECOND_PORT.write_u32s(&[ - // 0x3, // SPB type - // total_len, // Total block length - // len.saturating_cast::().saturating_add(8), // Packet length - //]); - //SECOND_PORT.write_bytes(&pid.to_ne_bytes()); - //#[expect( - // clippy::indexing_slicing, - // reason = "The truncated length is always <= the buffer's length" - //)] - //SECOND_PORT.write_bytes(&buffer[0..usize(trunc_len)]); - //for _ in 0..padding { - // SECOND_PORT.write_bytes(&[0]); - //} - //SECOND_PORT.write_u32s(&[ - // total_len, // Total block length - //]); + #[cfg(feature = "log-rpc")] + { + #[expect( + clippy::unwrap_used, + reason = "The min call guarantees that the value is in the range of a u32 before the cast" + )] + let trunc_len: u32 = usize::min(len, 4096).try_into().unwrap(); + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't underflow, as x % 4 < 4 no matter the x" + )] + let padding = if (trunc_len % 4) != 0 { 4 - (trunc_len % 4) } else { 0 }; + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't overflow, as padding is no more than 4 and trunc_len is no more than 4096." + )] + let padded_len = trunc_len + padding; + #[expect( + clippy::arithmetic_side_effects, + reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX" + )] + let total_len = padded_len + 8 + (4 * 4); + SECOND_PORT.write_u32s(&[ + 0x3, // SPB type + total_len, // Total block length + len.saturating_cast::().saturating_add(8), // Packet length + ]); + SECOND_PORT.write_bytes(&pid.to_ne_bytes()); + #[expect( + clippy::indexing_slicing, + reason = "The truncated length is always <= the buffer's length" + )] + SECOND_PORT.write_bytes(&buffer[0..usize(trunc_len)]); + for _ in 0..padding { + SECOND_PORT.write_bytes(&[0]); + } + SECOND_PORT.write_u32s(&[ + total_len, // Total block length + ]); + } let buf_num_pages = buffer.len() / 4096; let buffer = Box::into_raw(buffer); let buf_start_page = @@ -574,10 +578,6 @@ extern "C" fn syscall_handler() { clippy::unwrap_used, reason = "The PID is known valid due to using it in message_queue_mut in the if-let condition" )] - #[expect( - clippy::unwrap_used, - reason = "The PID is known valid due to using it in message_queue_mut in the if-let condition" - )] TASKING.wake(pid, SleepReason::WaitingForIPC).unwrap(); retval = 0; } else { diff --git a/src/main.rs b/src/main.rs index 0e5ff49..09d1496 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,6 @@ #![feature(allocator_api)] #![feature(naked_functions)] #![feature(stmt_expr_attributes)] -#![feature(exposed_provenance)] // #![feature(strict_provenance)] #![deny( unsafe_op_in_unsafe_fn, @@ -87,7 +86,6 @@ mod virtual_memory; use core::{ptr, slice}; -use alloc::ffi::CString; use bootinfo::BOOTINFO; use cast::usize; use elf::{ @@ -99,7 +97,6 @@ use elf::{ ElfBytes, }; use physical_memory::PHYSICAL_MEMORY; -use serial::SECOND_PORT; use spin::lazy::Lazy; use tar_no_std::TarArchiveRef; use tasking::{SleepReason, TASKING}; @@ -112,6 +109,9 @@ use x86_64::{ use crate::virtual_memory::AddressSpace; +#[cfg(feature = "log-rpc")] +use serial::SECOND_PORT; + // pub static INITRD: &[u8] = include_bytes!("../initrd.tar"); #[expect( @@ -270,28 +270,25 @@ pub fn main() { } } - //// Before starting init, write the pcapng section header + interface description to the second serial port - //SECOND_PORT.write_u32s(&[ - // 0x0A0D_0D0A, // SHB type - // 7 * 4, // Total block length - // 0x1A2B_3C4D, // Byte order magic - // 0x0000_0001, // Version (1.0) - // 0xFFFF_FFFF, // Length upper (-1) across both - // 0xFFFF_FFFF, // Length lower - // 7 * 4, // Total block length - // 0x1, // IDB type - // 5 * 4, // Total block length - // 147, // Link type - // 4096 + 8, // Packet length limit, - // 5 * 4, // Total block length - //]); + #[cfg(feature = "log-rpc")] + // Before starting init, write the pcapng section header + interface description to the second serial port + SECOND_PORT.write_u32s(&[ + 0x0A0D_0D0A, // SHB type + 7 * 4, // Total block length + 0x1A2B_3C4D, // Byte order magic + 0x0000_0001, // Version (1.0) + 0xFFFF_FFFF, // Length upper (-1) across both + 0xFFFF_FFFF, // Length lower + 7 * 4, // Total block length + 0x1, // IDB type + 5 * 4, // Total block length + 147, // Link type + 4096 + 8, // Packet length limit, + 5 * 4, // Total block length + ]); - #[expect( - clippy::unwrap_used, - reason = "Argument does not contain a null byte, thus this cannot panic" - )] let init_pid = TASKING .new_process(ptr::with_exposed_provenance(usize(init.ehdr.e_entry)), init_addr_space) .expect("Failed to create init process"); - TASKING.wake(init_pid, SleepReason::NewProcess).unwrap(); + TASKING.wake(init_pid, SleepReason::NewProcess).expect("Failed to wake new init process"); } diff --git a/src/serial.rs b/src/serial.rs index 95a8308..bd0d53e 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -11,6 +11,7 @@ pub static FIRST_PORT: Lazy = Lazy::new(|| { Wrapper(Mutex::new(port)) }); +#[cfg(feature = "log-rpc")] pub static SECOND_PORT: Lazy = Lazy::new(|| { // SAFETY: // 0x2f8 is the defined address for the second serial port on x86_64, @@ -45,13 +46,17 @@ impl Wrapper { #[macro_export] macro_rules! print { - ($($arg:tt)*) => ($crate::serial::_print(format_args!($($arg)*))); + ($($arg:tt)*) => ({ + #[expect(clippy::used_underscore_items, reason="_print is meant for this macro")] + $crate::serial::_print(format_args!($($arg)*)) + }) } #[macro_export] macro_rules! println { () => ($crate::print!("\r\n")); ($($arg:tt)*) => ({ + #[expect(clippy::used_underscore_items, reason="_print is meant for this macro")] $crate::serial::_print(format_args!($($arg)*)); $crate::print!("\r\n"); }) diff --git a/src/tasking.rs b/src/tasking.rs index a9855e9..6e97f2e 100644 --- a/src/tasking.rs +++ b/src/tasking.rs @@ -1,19 +1,18 @@ use crate::{ gdt, interrupts::{send_ipc_to, REGISTERD_PIDS}, - println, qemu_exit, + println, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE}, }; -use alloc::{boxed::Box, collections::VecDeque, string::ToString, vec::Vec}; +use alloc::{boxed::Box, collections::VecDeque, vec::Vec}; use cast::{u64, usize}; use core::{ arch::naked_asm, - ffi::CStr, ptr::{addr_of, addr_of_mut}, sync::atomic::{AtomicBool, Ordering}, }; use crossbeam_queue::SegQueue; -use humansize::{SizeFormatter, BINARY}; +//use humansize::{SizeFormatter, BINARY}; use slab::Slab; use spin::{Lazy, Mutex, RwLock}; use x86_64::{ @@ -258,15 +257,9 @@ impl Tasking { core::mem::drop(processes); switch_to_asm(curr_stack, kernel_esp); break; - } else if { - #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] - let res = self.processes.read()[current_pid].sleeping.read().is_some(); - res - } { - //println!("All processes sleeping, exiting QEMU"); - //self.print_stats(); - //qemu_exit::exit_qemu(); - //println!("All processes sleeping, waiting for interrupt"); + } else if #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] + self.processes.read()[current_pid].sleeping.read().is_some() + { self.wfi_loop.store(true, Ordering::Relaxed); x86_64::instructions::interrupts::enable_and_hlt(); x86_64::instructions::interrupts::disable(); @@ -318,7 +311,6 @@ impl Tasking { #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] let mut processes = self.processes.write(); if let Some(current_pid) = *self.current_pid.read() { - //self.freeable_kstacks.lock().push(processes.remove(current_pid).kernel_stack); *processes[current_pid].sleeping.write() = Some(SleepReason::Exited); } #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] @@ -339,11 +331,9 @@ impl Tasking { switch_to_asm_exit(kernel_esp); unreachable!() } else { - //println!("Last non-sleeping process exited, exiting QEMU"); self.wfi_loop.store(true, Ordering::Relaxed); x86_64::instructions::interrupts::enable_and_hlt(); x86_64::instructions::interrupts::disable(); - //self.exit(); } } } @@ -418,10 +408,6 @@ impl Tasking { Ok(func(aspace)) } - pub fn proc_sleeping(&self, pid: usize) -> Result, InvalidPid> { - Ok(*(self.processes.read().get(pid).ok_or(InvalidPid)?.sleeping.read())) - } - pub fn sleep(&self, reason: SleepReason) { #[warn(clippy::unwrap_used, reason = "FIXME")] #[warn(clippy::indexing_slicing, reason = "FIXME(?)")] @@ -442,20 +428,20 @@ impl Tasking { Ok(()) } - pub fn print_stats(&self) { - let mut total = KERNEL_SPACE.lock().get_bytes_allocated(); - println!( - "[TASKING] Kernel used {}", - SizeFormatter::new(KERNEL_SPACE.lock().get_bytes_allocated(), BINARY) - ); - for (i, process) in self.processes.read().iter() { - let bytes_used = process.address_space.as_ref().map_or_else( - || ACTIVE_SPACE.lock().get_bytes_allocated(), - |space| space.get_bytes_allocated(), - ); - total += bytes_used; - println!("[TASKING] PID {} used {}", i, SizeFormatter::new(bytes_used, BINARY),); - } - println!("[TASKING] Total used {} ({})", SizeFormatter::new(total, BINARY), total / 4096); - } + //pub fn print_stats(&self) { + // let mut total = KERNEL_SPACE.lock().get_bytes_allocated(); + // println!( + // "[TASKING] Kernel used {}", + // SizeFormatter::new(KERNEL_SPACE.lock().get_bytes_allocated(), BINARY) + // ); + // for (i, process) in self.processes.read().iter() { + // let bytes_used = process.address_space.as_ref().map_or_else( + // || ACTIVE_SPACE.lock().get_bytes_allocated(), + // |space| space.get_bytes_allocated(), + // ); + // total += bytes_used; + // println!("[TASKING] PID {} used {}", i, SizeFormatter::new(bytes_used, BINARY),); + // } + // println!("[TASKING] Total used {} ({})", SizeFormatter::new(total, BINARY), total / 4096); + //} } diff --git a/src/virtual_memory.rs b/src/virtual_memory.rs index c14876c..b407741 100644 --- a/src/virtual_memory.rs +++ b/src/virtual_memory.rs @@ -792,9 +792,9 @@ impl AddressSpace { self.bytes_allocated.fetch_sub(size, Ordering::Relaxed); } - pub fn get_bytes_allocated(&self) -> usize { - self.bytes_allocated.load(Ordering::Relaxed) - } + //pub fn get_bytes_allocated(&self) -> usize { + // self.bytes_allocated.load(Ordering::Relaxed) + //} } impl Drop for AddressSpace {