feat: terminal, start app by ID

This commit is contained in:
2026-03-26 15:27:08 +01:00
parent 804941d933
commit 02f16715bc
7 changed files with 53 additions and 19 deletions

View File

@@ -273,7 +273,7 @@ pub fn map_page(
let table = unsafe { &mut *table_ptr }; let table = unsafe { &mut *table_ptr };
if !table.0[l3_off].is_invalid() { 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); 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. // Verify virtual address is available.
if !table.0[l2_off].is_invalid() { 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); let new_entry = TableEntry::block_descriptor(physical_address, additional_flags);
@@ -392,7 +392,7 @@ fn next_table(
match table.0[offset].value & 0b11 { match table.0[offset].value & 0b11 {
0 => { 0 => {
if !create_missing { if !create_missing {
return Err(NovaError::Paging); return Err(NovaError::Paging("No table defined."));
} }
let new_phys_page_table_address = reserve_page(); 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) 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), 3 => Ok(resolve_table_addr(table.0[offset].address()) as *mut PageTable),
_ => unreachable!(), _ => unreachable!(),
} }

View File

@@ -24,7 +24,7 @@ pub fn reserve_page_explicit(physical_address: usize) -> Result<PhysAddr, NovaEr
let word_index = page / 64; let word_index = page / 64;
if unsafe { PAGING_BITMAP.bitmap[word_index] } & (1 << (page % 64)) > 0 { if unsafe { PAGING_BITMAP.bitmap[word_index] } & (1 << (page % 64)) > 0 {
return Err(NovaError::Paging); return Err(NovaError::Paging("Page PA already taken."));
} }
unsafe { PAGING_BITMAP.bitmap[word_index] |= 1 << (page % 64) }; 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 { for i in 0..L2_BLOCK_BITMAP_WORDS {
unsafe { unsafe {
if PAGING_BITMAP.bitmap[(page / 64) + i] != 0 { if PAGING_BITMAP.bitmap[(page / 64) + i] != 0 {
return Err(NovaError::Paging); return Err(NovaError::Paging("Block PA already taken."));
} }
}; };
} }

View File

@@ -7,6 +7,8 @@ use crate::{
}; };
use alloc::vec::Vec; use alloc::vec::Vec;
use core::arch::asm; use core::arch::asm;
use log::error;
use nova_error::NovaError;
use spin::Mutex; use spin::Mutex;
pub struct Application { pub struct Application {
@@ -28,7 +30,7 @@ impl Application {
) )
.unwrap(); .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)] #[allow(static_mut_refs)]
unsafe { unsafe {
let table = &mut *(virtual_address as *mut PageTable); let table = &mut *(virtual_address as *mut PageTable);
@@ -40,6 +42,13 @@ impl Application {
start_addr, 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) { pub fn start(&self) {
unsafe { unsafe {
asm!("msr ELR_EL1, {}", in(reg) self.start_addr); asm!("msr ELR_EL1, {}", in(reg) self.start_addr);
@@ -69,14 +78,27 @@ pub fn initialize_app_manager() {
let mut guard = APP_MANAGER.lock(); let mut guard = APP_MANAGER.lock();
guard.apps = Some(Vec::new()); 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() { if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() {
app_list.push(app); app_list.push(app);
Ok(())
} else {
Err(NovaError::General("AppManager not initalized."))
} }
} }
pub fn start_app(index: usize) { pub fn start_app(index: usize) -> Result<(), NovaError> {
if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() { if let Some(app) = APP_MANAGER
app_list[index].start(); .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."))
} }
} }

View File

@@ -20,12 +20,15 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr
log_sync_exception(); log_sync_exception();
match esr.ec { match esr.ec {
0b100100 => { 0b100100 => {
warn!("Cause: Data Abort from a lower Exception level"); error!("Cause: Data Abort from a lower Exception level");
} }
0b010101 => { 0b010101 => {
debug!("Cause: SVC instruction execution in AArch64"); debug!("Cause: SVC instruction execution in AArch64");
return handle_svc(frame); return handle_svc(frame);
} }
0b100010 => {
error!("Cause: PC alignment fault.");
}
_ => { _ => {
error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec); error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec);
} }

View File

@@ -105,7 +105,7 @@ pub extern "C" fn kernel_main() {
enable_irq_source(IRQSource::UartInt); enable_irq_source(IRQSource::UartInt);
let app = Application::new(el0 as *const () as usize); let app = Application::new(el0 as *const () as usize);
add_app(app); add_app(app).unwrap();
kernel_loop(); kernel_loop();
} }

View File

@@ -38,14 +38,20 @@ impl Terminal {
let val = self.input.clone(); let val = self.input.clone();
self.input.clear(); self.input.clear();
match val.as_str() { let mut parts = val.split(" ");
match parts.next().unwrap() {
"temp" => { "temp" => {
println!("{}", read_soc_temp([0]).unwrap()[1]); println!("{}", read_soc_temp([0]).unwrap()[1]);
} }
"el0" => unsafe { "app" => unsafe {
if let Some(app_id) = parts.next().and_then(|a| a.parse::<usize>().ok()) {
let i = 69; let i = 69;
asm!("", in("x0") i); asm!("", in("x0") i);
start_app(0); let _ = start_app(app_id);
} else {
println!("App ID not set.");
}
}, },
_ => { _ => {
println!("Unknown command: \"{}\"", self.input); println!("Unknown command: \"{}\"", self.input);

View File

@@ -5,11 +5,12 @@ use core::prelude::rust_2024::derive;
#[derive(Debug)] #[derive(Debug)]
pub enum NovaError { pub enum NovaError {
General(&'static str),
Mailbox, Mailbox,
HeapFull, HeapFull,
EmptyHeapSegmentNotAllowed, EmptyHeapSegmentNotAllowed,
Misalignment, Misalignment,
InvalidGranularity, InvalidGranularity,
Paging, Paging(&'static str),
OutOfMeomory, OutOfMeomory,
} }