From 0ddafd9976019fc7dcecd980db18559105839e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Sun, 22 Mar 2026 15:52:57 +0100 Subject: [PATCH 1/2] feat: basic terminal --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/framebuffer.rs | 8 ++- src/interrupt_handlers.rs | 15 +++--- src/interrupt_handlers/irq.rs | 12 +++-- src/interrupt_handlers/synchronous.rs | 26 +++++----- src/lib.rs | 41 +++++++++++++-- src/logger.rs | 45 ----------------- src/main.rs | 23 +++++---- src/terminal.rs | 73 +++++++++++++++++---------- tests/logger.rs | 44 ++++++++++++++++ 11 files changed, 179 insertions(+), 116 deletions(-) delete mode 100644 src/logger.rs create mode 100644 tests/logger.rs diff --git a/Cargo.lock b/Cargo.lock index 23658e2..c50c509 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,12 +40,19 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + [[package]] name = "nova" version = "0.1.0" dependencies = [ "heap", "libm", + "log", "nova_error", "paste", ] diff --git a/Cargo.toml b/Cargo.toml index e5a1c75..81e363e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ libm = "0.2.15" heap = {path = "workspace/heap"} nova_error = {path = "workspace/nova_error"} paste = "1.0.15" +log = "0.4.29" [workspace] diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 0102927..7cd247a 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -4,10 +4,8 @@ mod bitmaps; use bitmaps::BASIC_LEGACY; -use crate::{ - pi3::mailbox::{read_mailbox, write_mailbox}, - println, -}; +use crate::pi3::mailbox::{read_mailbox, write_mailbox}; +use log::error; #[repr(align(16))] struct Mailbox([u32; 36]); @@ -237,7 +235,7 @@ impl Default for FrameBuffer { let _ = read_mailbox(8); if mailbox.0[1] == 0 { - println!("Failed"); + error!("Mailbox request was not processed!"); } mailbox.0[28] &= 0x3FFFFFFF; diff --git a/src/interrupt_handlers.rs b/src/interrupt_handlers.rs index ab0a41b..e85742c 100644 --- a/src/interrupt_handlers.rs +++ b/src/interrupt_handlers.rs @@ -2,8 +2,9 @@ use core::arch::asm; use crate::{ aarch64::registers::{daif::mask_all, read_esr_el1, read_exception_source_el}, - get_current_el, println, + get_current_el, }; +use log::debug; const INTERRUPT_BASE: u32 = 0x3F00_B000; const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204; @@ -66,12 +67,12 @@ unsafe extern "C" fn rust_synchronous_interrupt_no_el_change() { mask_all(); let source_el = read_exception_source_el() >> 2; - println!("--------Sync Exception in EL{}--------", source_el); - println!("No EL change"); - println!("Current EL: {}", get_current_el()); - println!("{:?}", EsrElX::from(read_esr_el1())); - println!("Return register address: {:#x}", read_esr_el1()); - println!("-------------------------------------"); + debug!("--------Sync Exception in EL{}--------", source_el); + debug!("No EL change"); + debug!("Current EL: {}", get_current_el()); + debug!("{:?}", EsrElX::from(read_esr_el1())); + debug!("Return register address: {:#x}", read_esr_el1()); + debug!("-------------------------------------"); } fn set_return_to_kernel_main() { diff --git a/src/interrupt_handlers/irq.rs b/src/interrupt_handlers/irq.rs index 29d3388..f5b16e0 100644 --- a/src/interrupt_handlers/irq.rs +++ b/src/interrupt_handlers/irq.rs @@ -15,6 +15,8 @@ use crate::{ println, read_address, write_address, }; use alloc::vec::Vec; +use log::{debug, info}; + struct InterruptHandlers { source: IRQSource, function: fn(), @@ -60,9 +62,9 @@ unsafe extern "C" fn rust_irq_handler() { if pending_irqs & GPIO_PENDING_BIT_OFFSET != 0 { handle_gpio_interrupt(); let source_el = read_exception_source_el() >> 2; - println!("Source EL: {}", source_el); - println!("Current EL: {}", get_current_el()); - println!("Return register address: {:#x}", read_esr_el1()); + debug!("Source EL: {}", source_el); + debug!("Current EL: {}", get_current_el()); + debug!("Return register address: {:#x}", read_esr_el1()); } if let Some(handler_vec) = unsafe { &*core::ptr::addr_of_mut!(INTERRUPT_HANDLERS) } { @@ -76,7 +78,7 @@ unsafe extern "C" fn rust_irq_handler() { } fn handle_gpio_interrupt() { - println!("Interrupt"); + debug!("GPIO interrupt triggered"); for i in 0..=53u32 { let val = read_gpio_event_detect_status(i); @@ -84,7 +86,7 @@ fn handle_gpio_interrupt() { #[allow(clippy::single_match)] match i { 26 => { - println!("Button Pressed"); + info!("Button Pressed"); } _ => {} } diff --git a/src/interrupt_handlers/synchronous.rs b/src/interrupt_handlers/synchronous.rs index 2b20364..0df731f 100644 --- a/src/interrupt_handlers/synchronous.rs +++ b/src/interrupt_handlers/synchronous.rs @@ -3,9 +3,10 @@ use crate::{ get_current_el, interrupt_handlers::{set_return_to_kernel_main, EsrElX, TrapFrame}, pi3::mailbox, - println, }; +use log::{debug, error, info}; + /// Synchronous Exception Handler /// /// Source is a lower Exception level, where the implemented level @@ -15,21 +16,22 @@ use crate::{ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut TrapFrame) -> usize { mask_all(); let esr: EsrElX = EsrElX::from(read_esr_el1()); + debug!("Synchronous interrupt from lower EL triggered"); + log_sync_exception(); match esr.ec { 0b100100 => { - log_sync_exception(); - println!("Cause: Data Abort from a lower Exception level"); + debug!("Cause: Data Abort from a lower Exception level"); } 0b010101 => { - println!("Cause: SVC instruction execution in AArch64"); + debug!("Cause: SVC instruction execution in AArch64"); return handle_svc(frame); } _ => { - println!("Unknown Error Code: {:b}", esr.ec); + error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec); } } - println!("Returning to kernel main..."); + info!("Returning to kernel main..."); set_return_to_kernel_main(); 0 } @@ -46,11 +48,11 @@ fn handle_svc(frame: &mut TrapFrame) -> usize { fn log_sync_exception() { let source_el = read_exception_source_el() >> 2; - println!("--------Sync Exception in EL{}--------", source_el); - println!("Exception escalated to EL {}", get_current_el()); - println!("Current EL: {}", get_current_el()); + debug!("--------Sync Exception in EL{}--------", source_el); + debug!("Exception escalated to EL {}", get_current_el()); + debug!("Current EL: {}", get_current_el()); let esr: EsrElX = EsrElX::from(read_esr_el1()); - println!("{:?}", esr); - println!("Return address: {:#x}", read_elr_el1()); - println!("-------------------------------------"); + debug!("{:?}", esr); + debug!("Return address: {:#x}", read_elr_el1()); + debug!("-------------------------------------"); } diff --git a/src/lib.rs b/src/lib.rs index 19f5b29..56c8b3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,13 @@ extern crate alloc; -use alloc::boxed::Box; use core::{ arch::asm, panic::PanicInfo, ptr::{read_volatile, write_volatile}, }; +use log::LevelFilter; +use log::{Level, Metadata, Record}; use heap::Heap; @@ -17,11 +18,14 @@ use crate::{ allocate_memory, PhysSource, KERNEL_VIRTUAL_MEM_SPACE, LEVEL2_BLOCK_SIZE, NORMAL_MEM, UXN, WRITABLE, }, - interrupt_handlers::irq::initialize_interrupt_handler, - logger::DefaultLogger, + interrupt_handlers::irq::{ + initialize_interrupt_handler, register_interrupt_handler, IRQSource, + }, pi3::timer::sleep_s, + terminal::{flush_terminal, init_terminal}, }; +static LOGGER: UartLogger = UartLogger; static PERIPHERAL_BASE: usize = 0x3F00_0000; unsafe extern "C" { @@ -54,9 +58,9 @@ pub mod aarch64; pub mod configuration; pub mod framebuffer; pub mod interrupt_handlers; -pub mod logger; pub mod pi3; +pub mod terminal; #[inline(always)] pub unsafe fn read_address(address: u32) -> u32 { @@ -86,8 +90,35 @@ pub fn initialize_kernel() { if unsafe { KERNEL_INITIALIZED } { return; } + unsafe { init_kernel_heap() }; - logger::set_logger(Box::new(DefaultLogger)); initialize_interrupt_handler(); + init_terminal(); + unsafe { KERNEL_INITIALIZED = true }; } + +struct UartLogger; + +impl log::Log for UartLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= Level::Info + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + println!("{} - {}", record.level(), record.args()); + if record.level() <= Level::Info { + flush_terminal(); + } + } + } + + fn flush(&self) {} +} + +pub fn init_logger() { + log::set_logger(&LOGGER) + .map(|()| log::set_max_level(LevelFilter::Debug)) + .unwrap(); +} diff --git a/src/logger.rs b/src/logger.rs deleted file mode 100644 index c769551..0000000 --- a/src/logger.rs +++ /dev/null @@ -1,45 +0,0 @@ -use core::fmt::Write; - -use alloc::{boxed::Box, fmt}; - -use crate::peripherals::uart; - -static mut LOGGER: Option> = None; - -pub trait Logger: Write + Sync { - fn flush(&mut self); -} - -pub struct DefaultLogger; - -impl Logger for DefaultLogger { - fn flush(&mut self) {} -} - -impl Write for DefaultLogger { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - uart::Uart.write_str(s) - } -} - -#[macro_export] -macro_rules! log { - () => {}; - ($($arg:tt)*) => { - $crate::logger::log(format_args!($($arg)*)) - }; -} - -pub fn log(args: fmt::Arguments) { - if let Some(logger) = unsafe { &mut *core::ptr::addr_of_mut!(LOGGER) } { - logger.write_str("\n").unwrap(); - logger.write_fmt(args).unwrap(); - logger.flush(); - } -} - -pub fn set_logger(logger: Box) { - unsafe { - LOGGER = Some(logger); - } -} diff --git a/src/main.rs b/src/main.rs index 8bb9675..33a22d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use core::{ arch::{asm, global_asm}, ptr::write_volatile, }; +use log::{debug, info}; extern crate alloc; @@ -14,7 +15,7 @@ use nova::{ aarch64::registers::{daif, read_id_aa64mmfr0_el1}, configuration::memory_mapping::initialize_mmu_translation_tables, framebuffer::{FrameBuffer, BLUE, GREEN, RED}, - get_current_el, + get_current_el, init_logger, interrupt_handlers::irq::{enable_irq_source, IRQSource}, peripherals::{ gpio::{ @@ -60,16 +61,18 @@ pub extern "C" fn main() -> ! { // Set ACT Led to Outout let _ = set_gpio_function(21, GPIOFunction::Output); + init_logger(); - println!("Hello World!"); - println!("Exception level: {}", get_current_el()); + info!("Hello World!"); + info!("Current exception level: {}", get_current_el()); + info!("initializing MMU..."); initialize_mmu_translation_tables(); unsafe { configure_mmu_el1() }; - println!("MMU initialized..."); + info!("MMU configured!"); - println!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1()); - println!("Moving El2->EL1"); + debug!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1()); + info!("Moving El2->EL1"); unsafe { FRAMEBUFFER = Some(FrameBuffer::default()) }; unsafe { @@ -90,15 +93,16 @@ unsafe fn zero_bss() { #[no_mangle] pub extern "C" fn kernel_main() -> ! { - println!("Kernel Start..."); nova::initialize_kernel(); + info!("Kernel Initialized..."); + info!("Current exception Level: {}", get_current_el()); + let mut test_vector = Vec::new(); for i in 0..20 { test_vector.push(i); } - println!("heap allocation test: {:?}", test_vector); + debug!("heap allocation test: {:?}", test_vector); - println!("Exception Level: {}", get_current_el()); daif::unmask_all(); unsafe { @@ -136,7 +140,6 @@ pub extern "C" fn el0() -> ! { loop { let temp = syscall(67); - println!("{} °C", temp / 1000); blink_gpio(SpecificGpio::OnboardLed as u8, 500); } diff --git a/src/terminal.rs b/src/terminal.rs index 83b22a7..d0cf12b 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,53 +1,72 @@ -use core::fmt::Write; - use alloc::string::String; -use nova::{ - interrupt_handlers::register_interrupt_handler, logger::Logger, - peripherals::uart::read_uart_data, print, println, +use log::info; + +use crate::{ + interrupt_handlers::irq::{register_interrupt_handler, IRQSource}, + peripherals::uart::read_uart_data, + pi3::mailbox::read_soc_temp, + print, println, }; +pub static mut TERMINAL: Option = None; + pub struct Terminal { - buffer: String, input: String, } impl Terminal { pub fn new() -> Self { Self { - buffer: String::new(), input: String::new(), } } fn flush(&mut self) { - println!("{}", self.buffer); - print!("> {}", self.input); - self.buffer.clear(); + print!("\n> {}", self.input); } -} -impl Write for Terminal { - fn write_str(&mut self, s: &str) -> core::fmt::Result { - self.buffer.push_str(s); - Ok(()) + fn exec(&mut self) { + print!("\n"); + match self.input.as_str() { + "temp" => { + println!("{}", read_soc_temp([0]).unwrap()[1]); + } + _ => { + println!("Unknown command: \"{}\"", self.input); + } + } + self.input.clear(); } } +pub fn init_terminal() { + unsafe { TERMINAL = Some(Terminal::new()) }; + register_terminal_interrupt_handler(); +} -impl Logger for Terminal { - fn flush(&mut self) { - println!("{}", self.buffer); - print!("> {}", self.input); - self.buffer.clear(); +fn terminal_uart_rx_interrupt_handler() { + let input = read_uart_data(); + #[allow(static_mut_refs)] + if let Some(term) = unsafe { TERMINAL.as_mut() } { + match input { + '\r' => { + term.exec(); + term.flush(); + } + _ => { + term.input.push(input); + print!("{}", input); + } + } } } -fn terminal_uart_rx_interrupt_handler() { - print!("{}", read_uart_data()); +pub fn flush_terminal() { + #[allow(static_mut_refs)] + if let Some(term) = unsafe { TERMINAL.as_mut() } { + term.flush(); + } } -pub fn register_terminal_interrupt_handler() { - register_interrupt_handler( - nova::interrupt_handlers::IRQSource::UartInt, - terminal_uart_rx_interrupt_handler, - ); +fn register_terminal_interrupt_handler() { + register_interrupt_handler(IRQSource::UartInt, terminal_uart_rx_interrupt_handler); } diff --git a/tests/logger.rs b/tests/logger.rs new file mode 100644 index 0000000..b562c67 --- /dev/null +++ b/tests/logger.rs @@ -0,0 +1,44 @@ +use alloc::fmt; + +use crate::peripherals::uart::_print; + +#[repr(usize)] +pub enum LogLevel { + Error = 1, + Warn = 2, + Info = 3, + Debug = 4, +} + +#[macro_export] +macro_rules! info { + () => {}; + ($($arg:tt)*) => { + $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Info) + }; +} +#[macro_export] +macro_rules! debug { + () => {}; + ($($arg:tt)*) => { + $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Debug) + }; +} +#[macro_export] +macro_rules! err { + () => {}; + ($($arg:tt)*) => { + $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Error) + }; +} +#[macro_export] +macro_rules! warn { + () => {}; + ($($arg:tt)*) => { + $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Warn) + }; +} + +pub fn log(args: fmt::Arguments, level: LogLevel) { + _print(args); +} From 4ecc6ad86ede1a0eee2e9b556b14917ee4089f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Tue, 24 Mar 2026 17:44:05 +0100 Subject: [PATCH 2/2] feat: execute application via terminal --- .gitignore | 1 + .vscode/launch.json | 9 ++---- src/aarch64/mmu.rs | 36 +++++++++++++++++++++- src/config.S | 3 +- src/configuration/memory_mapping.rs | 3 ++ src/interrupt_handlers.rs | 4 +-- src/interrupt_handlers/irq.rs | 2 +- src/interrupt_handlers/synchronous.rs | 10 +++--- src/lib.rs | 18 +++-------- src/main.rs | 42 +++++++++++++++++-------- src/terminal.rs | 24 +++++++++++++-- tests/logger.rs | 44 --------------------------- workspace/nova_error/src/lib.rs | 1 + 13 files changed, 108 insertions(+), 89 deletions(-) delete mode 100644 tests/logger.rs diff --git a/.gitignore b/.gitignore index 1bc1b3f..3e3ad8f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ sd.img settings.json .DS_Store .venv +.nvimlog diff --git a/.vscode/launch.json b/.vscode/launch.json index 77dba6e..00f9603 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -58,15 +58,12 @@ ], "preLaunchTask": "Run QEMU wo window" }, - { - "name": "Attach LLDB", + "name": "LLDB", "type": "lldb", - "request": "attach", - "debugServer": 1234, + "request": "launch", "program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova", - "stopOnEntry": true, - "processCreateCommands": ["gdb-remote localhost:1234"] + "preLaunchTask": "Run QEMU wo window" } ] } diff --git a/src/aarch64/mmu.rs b/src/aarch64/mmu.rs index 50aac0c..0762a95 100644 --- a/src/aarch64/mmu.rs +++ b/src/aarch64/mmu.rs @@ -106,6 +106,18 @@ pub enum PhysSource { #[repr(align(4096))] pub struct PageTable([TableEntry; TABLE_ENTRY_COUNT]); +impl Iterator for PageTable { + type Item = VirtAddr; + + fn next(&mut self) -> Option { + for (offset, entity) in self.0.iter().enumerate() { + if entity.is_invalid() { + return Some(offset); + } + } + None + } +} #[no_mangle] pub static mut TRANSLATIONTABLE_TTBR0: PageTable = PageTable([TableEntry { value: 0 }; 512]); #[no_mangle] @@ -197,7 +209,7 @@ fn map_range_dynamic( /// Allocate a singe page. pub fn alloc_page( - virtual_address: usize, + virtual_address: VirtAddr, base_table: *mut PageTable, additional_flags: u64, ) -> Result<(), NovaError> { @@ -209,6 +221,28 @@ pub fn alloc_page( ) } +/// Allocate a singe page in one block. +pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result { + if !start.is_multiple_of(GRANULARITY) { + return Err(NovaError::Misalignment); + } + + let (off1, off2, _) = virtual_address_to_table_offset(start); + let offsets = [off1, off2]; + let table = unsafe { + &mut *navigate_table( + core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR1), + &offsets, + true, + )? + }; + + if let Some(virt_addr) = table.next() { + return Ok(virt_addr); + } + Err(NovaError::OutOfMeomory) +} + /// Allocate a single page at an explicit `physical_address`. pub fn alloc_page_explicit( virtual_address: usize, diff --git a/src/config.S b/src/config.S index 619f33c..5e13a6d 100644 --- a/src/config.S +++ b/src/config.S @@ -77,7 +77,7 @@ configure_mmu_el1: .align 4 .global el1_to_el0 el1_to_el0: - + mov x8, x0 // Set SPSR_EL1: return to EL0t mov x0, #(0b0000) msr SPSR_EL1, x0 @@ -93,5 +93,6 @@ el1_to_el0: isb + mov x0, x8 // Return to EL0 eret diff --git a/src/configuration/memory_mapping.rs b/src/configuration/memory_mapping.rs index 2d0c21c..2adbcee 100644 --- a/src/configuration/memory_mapping.rs +++ b/src/configuration/memory_mapping.rs @@ -19,6 +19,8 @@ pub const EL0_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2; pub const MAILBOX_VIRTUAL_ADDRESS: VirtAddr = 0xFFFF_FF81_FFFF_E000; pub static mut MAILBOX_PHYSICAL_ADDRESS: Option = None; +pub const APPLICATION_TRANSLATION_TABLE_VA: VirtAddr = 0xFFFF_FF81_FE00_0000; + extern "C" { static __text_end: u64; static __share_end: u64; @@ -99,6 +101,7 @@ pub fn initialize_mmu_translation_tables() { ) .unwrap(); + // Allocate Mailbox buffer { let addr = reserve_page(); unsafe { MAILBOX_PHYSICAL_ADDRESS = Some(addr) }; diff --git a/src/interrupt_handlers.rs b/src/interrupt_handlers.rs index e85742c..d2df3c8 100644 --- a/src/interrupt_handlers.rs +++ b/src/interrupt_handlers.rs @@ -75,9 +75,9 @@ unsafe extern "C" fn rust_synchronous_interrupt_no_el_change() { debug!("-------------------------------------"); } -fn set_return_to_kernel_main() { +fn set_return_to_kernel_loop() { unsafe { - asm!("ldr x0, =kernel_main", "msr ELR_EL1, x0"); + asm!("ldr x0, =kernel_loop", "msr ELR_EL1, x0"); asm!("mov x0, #(0b0101)", "msr SPSR_EL1, x0"); } } diff --git a/src/interrupt_handlers/irq.rs b/src/interrupt_handlers/irq.rs index f5b16e0..f7cc3ad 100644 --- a/src/interrupt_handlers/irq.rs +++ b/src/interrupt_handlers/irq.rs @@ -12,7 +12,7 @@ use crate::{ gpio::{read_gpio_event_detect_status, reset_gpio_event_detect_status}, uart::clear_uart_interrupt_state, }, - println, read_address, write_address, + read_address, write_address, }; use alloc::vec::Vec; use log::{debug, info}; diff --git a/src/interrupt_handlers/synchronous.rs b/src/interrupt_handlers/synchronous.rs index 0df731f..8f06c70 100644 --- a/src/interrupt_handlers/synchronous.rs +++ b/src/interrupt_handlers/synchronous.rs @@ -1,11 +1,11 @@ use crate::{ aarch64::registers::{daif::mask_all, read_elr_el1, read_esr_el1, read_exception_source_el}, get_current_el, - interrupt_handlers::{set_return_to_kernel_main, EsrElX, TrapFrame}, + interrupt_handlers::{set_return_to_kernel_loop, EsrElX, TrapFrame}, pi3::mailbox, }; -use log::{debug, error, info}; +use log::{debug, error, warn}; /// Synchronous Exception Handler /// @@ -20,7 +20,7 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr log_sync_exception(); match esr.ec { 0b100100 => { - debug!("Cause: Data Abort from a lower Exception level"); + warn!("Cause: Data Abort from a lower Exception level"); } 0b010101 => { debug!("Cause: SVC instruction execution in AArch64"); @@ -31,8 +31,8 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr } } - info!("Returning to kernel main..."); - set_return_to_kernel_main(); + warn!("UnhandledException -> Returning to kernel..."); + set_return_to_kernel_loop(); 0 } diff --git a/src/lib.rs b/src/lib.rs index 56c8b3a..25b0865 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,7 @@ use crate::{ allocate_memory, PhysSource, KERNEL_VIRTUAL_MEM_SPACE, LEVEL2_BLOCK_SIZE, NORMAL_MEM, UXN, WRITABLE, }, - interrupt_handlers::irq::{ - initialize_interrupt_handler, register_interrupt_handler, IRQSource, - }, + interrupt_handlers::irq::initialize_interrupt_handler, pi3::timer::sleep_s, terminal::{flush_terminal, init_terminal}, }; @@ -35,7 +33,7 @@ unsafe extern "C" { #[global_allocator] pub static mut GLOBAL_ALLOCATOR: Heap = Heap::empty(); -pub unsafe fn init_kernel_heap() { +pub unsafe fn initialize_kernel_heap() { let start = core::ptr::addr_of_mut!(__kernel_end) as usize | KERNEL_VIRTUAL_MEM_SPACE; let size = LEVEL2_BLOCK_SIZE * 2; @@ -84,25 +82,17 @@ pub fn get_current_el() -> u64 { el >> 2 } -static mut KERNEL_INITIALIZED: bool = false; - pub fn initialize_kernel() { - if unsafe { KERNEL_INITIALIZED } { - return; - } - - unsafe { init_kernel_heap() }; + unsafe { initialize_kernel_heap() }; initialize_interrupt_handler(); init_terminal(); - - unsafe { KERNEL_INITIALIZED = true }; } struct UartLogger; impl log::Log for UartLogger { fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Info + metadata.level() <= Level::Debug } fn log(&self, record: &Record) { diff --git a/src/main.rs b/src/main.rs index 33a22d4..0b1d814 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ use nova::{ }, uart::uart_init, }, - println, + print, println, }; global_asm!(include_str!("vector.S")); @@ -34,7 +34,6 @@ static mut FRAMEBUFFER: Option = None; extern "C" { fn el2_to_el1(); - fn el1_to_el0(); fn configure_mmu_el1(); static mut __bss_start: u32; static mut __bss_end: u32; @@ -92,7 +91,7 @@ unsafe fn zero_bss() { } #[no_mangle] -pub extern "C" fn kernel_main() -> ! { +pub extern "C" fn kernel_main() { nova::initialize_kernel(); info!("Kernel Initialized..."); info!("Current exception Level: {}", get_current_el()); @@ -103,18 +102,21 @@ pub extern "C" fn kernel_main() -> ! { } debug!("heap allocation test: {:?}", test_vector); - daif::unmask_all(); + enable_irq_source(IRQSource::UartInt); - unsafe { - el1_to_el0(); - }; + kernel_loop(); +} + +#[no_mangle] +pub extern "C" fn kernel_loop() { + daif::unmask_all(); #[allow(clippy::empty_loop)] loop {} } #[no_mangle] -pub extern "C" fn el0() -> ! { +pub extern "C" fn el0(input: usize) { println!("Jumped into EL0"); // Set GPIO 26 to Input @@ -123,8 +125,6 @@ pub extern "C" fn el0() -> ! { gpio_pull_up(26); set_falling_edge_detect(26, true); - enable_irq_source(IRQSource::UartInt); - if let Some(fb) = unsafe { FRAMEBUFFER.as_mut() } { for i in 0..1080 { fb.draw_pixel(50, i, BLUE); @@ -138,11 +138,27 @@ pub extern "C" fn el0() -> ! { fb.draw_function(cos, 0, 101, RED); } - loop { - let temp = syscall(67); + let _temp = syscall(67); + + println!("Calculting prime to: {}", input); - blink_gpio(SpecificGpio::OnboardLed as u8, 500); + for i in 3..input { + let mut is_prime = true; + for j in 3..i { + if i == j { + continue; + } + if i % j == 0 { + is_prime = false; + } + } + if is_prime { + print!("{} ", i); + } } + println!(""); + + blink_gpio(SpecificGpio::OnboardLed as u8, 500); } fn cos(x: u32) -> f64 { diff --git a/src/terminal.rs b/src/terminal.rs index d0cf12b..f64dd33 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,5 +1,6 @@ +use core::arch::asm; + use alloc::string::String; -use log::info; use crate::{ interrupt_handlers::irq::{register_interrupt_handler, IRQSource}, @@ -14,6 +15,16 @@ pub struct Terminal { input: String, } +extern "C" { + fn el1_to_el0(); +} + +impl Default for Terminal { + fn default() -> Self { + Self::new() + } +} + impl Terminal { pub fn new() -> Self { Self { @@ -27,10 +38,18 @@ impl Terminal { fn exec(&mut self) { print!("\n"); - match self.input.as_str() { + let val = self.input.clone(); + self.input.clear(); + + match val.as_str() { "temp" => { println!("{}", read_soc_temp([0]).unwrap()[1]); } + "el0" => unsafe { + let i = 69; + asm!("", in("x0") i); + el1_to_el0(); + }, _ => { println!("Unknown command: \"{}\"", self.input); } @@ -38,6 +57,7 @@ impl Terminal { self.input.clear(); } } + pub fn init_terminal() { unsafe { TERMINAL = Some(Terminal::new()) }; register_terminal_interrupt_handler(); diff --git a/tests/logger.rs b/tests/logger.rs deleted file mode 100644 index b562c67..0000000 --- a/tests/logger.rs +++ /dev/null @@ -1,44 +0,0 @@ -use alloc::fmt; - -use crate::peripherals::uart::_print; - -#[repr(usize)] -pub enum LogLevel { - Error = 1, - Warn = 2, - Info = 3, - Debug = 4, -} - -#[macro_export] -macro_rules! info { - () => {}; - ($($arg:tt)*) => { - $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Info) - }; -} -#[macro_export] -macro_rules! debug { - () => {}; - ($($arg:tt)*) => { - $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Debug) - }; -} -#[macro_export] -macro_rules! err { - () => {}; - ($($arg:tt)*) => { - $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Error) - }; -} -#[macro_export] -macro_rules! warn { - () => {}; - ($($arg:tt)*) => { - $crate::logger::log(format_args!($($arg)*), $crate::logger::LogLevel::Warn) - }; -} - -pub fn log(args: fmt::Arguments, level: LogLevel) { - _print(args); -} diff --git a/workspace/nova_error/src/lib.rs b/workspace/nova_error/src/lib.rs index bc32817..266905c 100644 --- a/workspace/nova_error/src/lib.rs +++ b/workspace/nova_error/src/lib.rs @@ -11,4 +11,5 @@ pub enum NovaError { Misalignment, InvalidGranularity, Paging, + OutOfMeomory, }