From 02f16715bc2b076ed954fd9459b55326e0cab135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Thu, 26 Mar 2026 15:27:08 +0100 Subject: [PATCH] feat: terminal, start app by ID --- src/aarch64/mmu.rs | 10 +++++---- src/aarch64/mmu/physical_mapping.rs | 4 ++-- src/application_manager.rs | 32 ++++++++++++++++++++++----- src/interrupt_handlers/synchronous.rs | 5 ++++- src/main.rs | 2 +- src/terminal.rs | 16 +++++++++----- workspace/nova_error/src/lib.rs | 3 ++- 7 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/aarch64/mmu.rs b/src/aarch64/mmu.rs index b090742..dc49715 100644 --- a/src/aarch64/mmu.rs +++ b/src/aarch64/mmu.rs @@ -273,7 +273,7 @@ pub fn map_page( let table = unsafe { &mut *table_ptr }; if !table.0[l3_off].is_invalid() { - return Err(NovaError::Paging); + return Err(NovaError::Paging("Page already occupied.")); } table.0[l3_off] = TableEntry::page_descriptor(physical_address, additional_flags); @@ -315,7 +315,7 @@ pub fn map_l2_block( // Verify virtual address is available. if !table.0[l2_off].is_invalid() { - return Err(NovaError::Paging); + return Err(NovaError::Paging("Block already occupied.")); } let new_entry = TableEntry::block_descriptor(physical_address, additional_flags); @@ -392,7 +392,7 @@ fn next_table( match table.0[offset].value & 0b11 { 0 => { if !create_missing { - return Err(NovaError::Paging); + return Err(NovaError::Paging("No table defined.")); } let new_phys_page_table_address = reserve_page(); @@ -406,7 +406,9 @@ fn next_table( Ok(resolve_table_addr(table.0[offset].address()) as *mut PageTable) } - 1 => Err(NovaError::Paging), + 1 => Err(NovaError::Paging( + "Can't navigate table due to block mapping.", + )), 3 => Ok(resolve_table_addr(table.0[offset].address()) as *mut PageTable), _ => unreachable!(), } diff --git a/src/aarch64/mmu/physical_mapping.rs b/src/aarch64/mmu/physical_mapping.rs index 641d20b..c3cb0d1 100644 --- a/src/aarch64/mmu/physical_mapping.rs +++ b/src/aarch64/mmu/physical_mapping.rs @@ -24,7 +24,7 @@ pub fn reserve_page_explicit(physical_address: usize) -> Result 0 { - return Err(NovaError::Paging); + return Err(NovaError::Paging("Page PA already taken.")); } unsafe { PAGING_BITMAP.bitmap[word_index] |= 1 << (page % 64) }; @@ -47,7 +47,7 @@ pub fn reserve_block_explicit(physical_address: usize) -> Result<(), NovaError> for i in 0..L2_BLOCK_BITMAP_WORDS { unsafe { if PAGING_BITMAP.bitmap[(page / 64) + i] != 0 { - return Err(NovaError::Paging); + return Err(NovaError::Paging("Block PA already taken.")); } }; } diff --git a/src/application_manager.rs b/src/application_manager.rs index adc4a40..f3e3c67 100644 --- a/src/application_manager.rs +++ b/src/application_manager.rs @@ -7,6 +7,8 @@ use crate::{ }; use alloc::vec::Vec; use core::arch::asm; +use log::error; +use nova_error::NovaError; use spin::Mutex; pub struct Application { @@ -28,7 +30,7 @@ impl Application { ) .unwrap(); - // TODO: Temporary fix, while kernel and app share some memory regions + // TODO: Temporary solution, while kernel and app share some memory regions #[allow(static_mut_refs)] unsafe { let table = &mut *(virtual_address as *mut PageTable); @@ -40,6 +42,13 @@ impl Application { start_addr, } } + + /// Starts an application. + /// + /// `ELR_EL1` -> Exception Link Register (starting virtual address) + /// `SPSR_EL1` -> Saved Program State Register (settings for `eret` behaviour) + /// `SP_EL0` -> Stack Pointer Register (virtual_address of stack Pointer) + /// `TTBR0_EL1` -> Translation Table base Register Register pub fn start(&self) { unsafe { asm!("msr ELR_EL1, {}", in(reg) self.start_addr); @@ -69,14 +78,27 @@ pub fn initialize_app_manager() { let mut guard = APP_MANAGER.lock(); guard.apps = Some(Vec::new()); } -pub fn add_app(app: Application) { + +pub fn add_app(app: Application) -> Result<(), NovaError> { if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() { app_list.push(app); + Ok(()) + } else { + Err(NovaError::General("AppManager not initalized.")) } } -pub fn start_app(index: usize) { - if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() { - app_list[index].start(); +pub fn start_app(index: usize) -> Result<(), NovaError> { + if let Some(app) = APP_MANAGER + .lock() + .apps + .as_mut() + .and_then(|am| am.get(index)) + { + app.start(); + unreachable!() + } else { + error!("Unable to start app due to invalid App ID."); + Err(NovaError::General("Invalid app id.")) } } diff --git a/src/interrupt_handlers/synchronous.rs b/src/interrupt_handlers/synchronous.rs index 8f06c70..b7f757c 100644 --- a/src/interrupt_handlers/synchronous.rs +++ b/src/interrupt_handlers/synchronous.rs @@ -20,12 +20,15 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr log_sync_exception(); match esr.ec { 0b100100 => { - warn!("Cause: Data Abort from a lower Exception level"); + error!("Cause: Data Abort from a lower Exception level"); } 0b010101 => { debug!("Cause: SVC instruction execution in AArch64"); return handle_svc(frame); } + 0b100010 => { + error!("Cause: PC alignment fault."); + } _ => { error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec); } diff --git a/src/main.rs b/src/main.rs index 0de0492..6d5971e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -105,7 +105,7 @@ pub extern "C" fn kernel_main() { enable_irq_source(IRQSource::UartInt); let app = Application::new(el0 as *const () as usize); - add_app(app); + add_app(app).unwrap(); kernel_loop(); } diff --git a/src/terminal.rs b/src/terminal.rs index db299a2..62feeb4 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -38,14 +38,20 @@ impl Terminal { let val = self.input.clone(); self.input.clear(); - match val.as_str() { + let mut parts = val.split(" "); + + match parts.next().unwrap() { "temp" => { println!("{}", read_soc_temp([0]).unwrap()[1]); } - "el0" => unsafe { - let i = 69; - asm!("", in("x0") i); - start_app(0); + "app" => unsafe { + if let Some(app_id) = parts.next().and_then(|a| a.parse::().ok()) { + let i = 69; + asm!("", in("x0") i); + let _ = start_app(app_id); + } else { + println!("App ID not set."); + } }, _ => { println!("Unknown command: \"{}\"", self.input); diff --git a/workspace/nova_error/src/lib.rs b/workspace/nova_error/src/lib.rs index 266905c..1686222 100644 --- a/workspace/nova_error/src/lib.rs +++ b/workspace/nova_error/src/lib.rs @@ -5,11 +5,12 @@ use core::prelude::rust_2024::derive; #[derive(Debug)] pub enum NovaError { + General(&'static str), Mailbox, HeapFull, EmptyHeapSegmentNotAllowed, Misalignment, InvalidGranularity, - Paging, + Paging(&'static str), OutOfMeomory, }