From 5a41a9c6a983972821d5f911b2dda5bd0248dcf3 Mon Sep 17 00:00:00 2001 From: August Date: Tue, 4 Nov 2025 19:58:42 -0500 Subject: [PATCH] Allocate space and create new page table --- src/kernel/arch/x86_64/paging.rs | 14 ++++++++++++ src/kernel/arch/x86_64/serial.rs | 29 +++++++++++++++++++++++- src/kernel/main.rs | 21 +++++++++++++---- src/kernel/memory.rs | 4 ++-- src/lib/syscall/mod.rs | 39 +++++++++++++++++++++++--------- 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/kernel/arch/x86_64/paging.rs b/src/kernel/arch/x86_64/paging.rs index 5d3abaf..1c49e82 100644 --- a/src/kernel/arch/x86_64/paging.rs +++ b/src/kernel/arch/x86_64/paging.rs @@ -5,12 +5,26 @@ use crate::constants::KERNEL_BUILD_PROFILE; use crate::{LOGGER, LogLevel, format, log_info, log_trace, memory::HHDM_RESPONSE}; +use free_list::{PAGE_SIZE, PageLayout}; use x86_64::{ PhysAddr, VirtAddr, registers::control::*, structures::paging::{PageTable, PageTableFlags}, }; +pub fn switch_ptable() { + let allocated_region = crate::memory::FREELIST + .lock() + .allocate(PageLayout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) + .expect("Could not allocate pages for new page table!"); + log_info!("Got region for new PML4: 0x{:x}", allocated_region.start()); + let pml4_start_vaddr = allocated_region.start() + HHDM_RESPONSE.offset() as usize; + let pml4_ptr = pml4_start_vaddr as *mut PageTable; + let mut pml4 = unsafe { crate::memory::alloc::boxed::Box::from_raw(pml4_ptr) }; + *pml4 = PageTable::new(); + log_info!("Initialized page table at 0x{:p}", pml4); +} + pub fn get_mappings() { log_info!("Paging: {}", Cr0::read().contains(Cr0Flags::PAGING)); log_info!( diff --git a/src/kernel/arch/x86_64/serial.rs b/src/kernel/arch/x86_64/serial.rs index 8eb640a..c0b4605 100644 --- a/src/kernel/arch/x86_64/serial.rs +++ b/src/kernel/arch/x86_64/serial.rs @@ -161,7 +161,7 @@ impl SerialPort { } /// Create a new port-mapped serial port with the base address `port_addr`. - pub fn new(port_addr: u16) -> Self { + pub unsafe fn from_port_unchecked(port_addr: u16) -> Self { let mut port = SerialPort { base_port: Port::new(port_addr), interrupt_enable: Port::new(port_addr + 1), @@ -180,6 +180,33 @@ impl SerialPort { port } + pub fn try_from_port(port_addr: u16) -> Option { + let mut port = unsafe { SerialPort::from_port_unchecked(port_addr) }; + + // Assert that port scratch register is writable + unsafe { port.scratch.write(192) }; + if unsafe { port.scratch.read() } != 192 { + return None; + } + + // Enable loopback mode + let mut port_modem = port.get_modem_control(); + port_modem.insert(ModemControl::Loop); + port.set_modem_control(port_modem); + port.write_char(0xae as char); + + // Assert that loopback mode worked + if port.read_char() != (0xae as u8) { + return None; + } + + // Disable loopback mode + port_modem.remove(ModemControl::Loop); + port.set_modem_control(port_modem); + + Some(port) + } + fn get_line_control(&mut self) -> u8 { unsafe { self.line_control.read() } } diff --git a/src/kernel/main.rs b/src/kernel/main.rs index a5d0e2f..32a7cf7 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -37,18 +37,20 @@ use spin::mutex::Mutex; use crate::arch::x86_64::cpuid::{CPUID, virt_supported}; lazy_static! { - pub static ref SERIAL_3F8: Mutex = - Mutex::new(arch::x86_64::serial::SerialPort::new(0x3f8)); + pub static ref SERIAL_3F8: Mutex = Mutex::new( + arch::x86_64::serial::SerialPort::try_from_port(0x3f8).expect("Could not create port") + ); } #[unsafe(no_mangle)] unsafe extern "C" fn main() -> ! { + // CRITICAL AREA + // Nothing non-essential should be done until we can initialize logging + // Otherwise it will fail silently + // Assert supported bootloader version assert!(BASE_REVISION.is_supported()); - // Ensure IDT exists - IDT.load(); - // Set up logging level from params // Nothing we can do here if this fails since no log subscribers are initialized yet if let Some(level) = PARAMS.get("-loglevel") @@ -69,6 +71,13 @@ unsafe extern "C" fn main() -> ! { } log_trace!("Configured kernel logging devices"); } + + // END OF CRITICAL AREA + // Fallible code can be placed below this comment + + // Ensure IDT exists + IDT.load(); + log_info!( "Kernel cmdline: {}", String::from_utf8_lossy( @@ -150,5 +159,7 @@ unsafe extern "C" fn main() -> ! { } log_info!("Virtualization provider: {:?}", virt_supported()); + arch::x86_64::paging::switch_ptable(); + panic!("Finished boot, but cannot start init because processes not implemented!"); } diff --git a/src/kernel/memory.rs b/src/kernel/memory.rs index b75b457..826dd81 100644 --- a/src/kernel/memory.rs +++ b/src/kernel/memory.rs @@ -19,8 +19,8 @@ use talc::*; pub extern crate alloc; -static FREELIST: Mutex> = Mutex::new(FreeList::<32>::new()); -static HW_FREELIST: Mutex> = Mutex::new(FreeList::<32>::new()); +pub static FREELIST: Mutex> = Mutex::new(FreeList::<32>::new()); +pub static HW_FREELIST: Mutex> = Mutex::new(FreeList::<32>::new()); lazy_static! { pub static ref MEMMAP_RESPONSE: &'static MemoryMapResponse = MEMMAP_REQUEST diff --git a/src/lib/syscall/mod.rs b/src/lib/syscall/mod.rs index a365c4b..dbe651f 100644 --- a/src/lib/syscall/mod.rs +++ b/src/lib/syscall/mod.rs @@ -1,33 +1,45 @@ + use num_derive::FromPrimitive; use num_traits::FromPrimitive; use crate::arch; - +#[repr(u32)] #[derive(FromPrimitive, Debug)] pub enum Syscall { - Exit, - Pid, - Message, - MemMap, - MemUnmap, - Resolve, - Spawn, - Version, - Yield, + /// Kill the calling process, and deallocate all + /// resources associated, including shared memory channels, + /// IPC sessions, handles, etc. + /// Arguments: + /// 0 - Exit code + Exit = 0, + /// Get the current PID of the calling process. + Pid = 1, + /// Send a message to another process. + Message = 2, + MemMap = 3, + MemUnmap = 4, + Resolve = 5, + Spawn = 6, + Version = 7, + Yield = 8, } +#[repr(u32)] #[derive(FromPrimitive, Debug)] pub enum SyscallStatus { + /// Syscall completed without any issues. Success, + /// Issued a system call with the wrong call ID. NoSuchCall, NoSuchProcess, NoSuchService, - NoPermission, + SecurityFailure, OutOfMemory, Aborted, Unspecified, Unknown, Unimplemented, + InvalidPage, } impl From for SyscallStatus { @@ -35,3 +47,8 @@ impl From for SyscallStatus { SyscallStatus::from_u64(value).unwrap_or(Self::Unknown) } } + +pub fn exit(code: u32) -> ! { + arch::syscall_impl::caller_syscall_1(Syscall::Exit as u64, code as u64); + unreachable!(); +} \ No newline at end of file