diff --git a/.gitignore b/.gitignore index 3e3ad8f..eacde57 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,8 @@ settings.json .DS_Store .venv .nvimlog +__pycache__ +.pytest_cache + +build/ + diff --git a/.vscode/launch.json b/.vscode/launch.json index 00f9603..7257aa3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,7 +3,7 @@ "compounds": [ { "name": "Run QEMU + Attach LLDB", - "configurations": ["Attach LLDB"], + "configurations": ["LLDB"], "preLaunchTask": "Run QEMU" } ], @@ -61,9 +61,21 @@ { "name": "LLDB", "type": "lldb", - "request": "launch", + "request": "attach", "program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova", - "preLaunchTask": "Run QEMU wo window" + "preLaunchTask": "Run QEMU", + "stopOnEntry": true, + "processCreateCommands": ["gdb-remote localhost:1234"] + }, + + { + "name": "NVIM LLDB", + "type": "codelldb", + "request": "attach", + "program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova", + "preLaunchTask": "Run QEMU", + "stopOnEntry": true, + "processCreateCommands": ["gdb-remote localhost:1234"] } ] } diff --git a/Cargo.lock b/Cargo.lock index c50c509..84935db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,15 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" @@ -55,6 +64,7 @@ dependencies = [ "log", "nova_error", "paste", + "spin", ] [[package]] @@ -129,6 +139,21 @@ dependencies = [ "getrandom", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + [[package]] name = "syn" version = "2.0.111" diff --git a/Cargo.toml b/Cargo.toml index 81e363e..489b8b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ heap = {path = "workspace/heap"} nova_error = {path = "workspace/nova_error"} paste = "1.0.15" log = "0.4.29" +spin = "0.10.0" [workspace] diff --git a/README.md b/README.md index 3bd4200..96fdc80 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ NovaOS is a expository project where I build a kernel from scratch for a Raspberry PI 3 B+. -[Technical write-up](https://leafnova.net/projects/pi3_kernel/) - ## Features - Delay and sleep ✓ @@ -16,9 +14,9 @@ NovaOS is a expository project where I build a kernel from scratch for a Raspber - Heap Memory allocation ✓ - MMU ✓ - SVC instructions ~ +- Basic Console over UART ~ +- Multi Applications ~ - Multi Core -- Multi Applications - Dynamic clock speed - Kernel Independent Applications - Multiprocessing -- Basic Terminal over UART diff --git a/src/aarch64/mmu.rs b/src/aarch64/mmu.rs index 0762a95..dc49715 100644 --- a/src/aarch64/mmu.rs +++ b/src/aarch64/mmu.rs @@ -43,7 +43,8 @@ const L2_BLOCK_BITMAP_WORDS: usize = LEVEL2_BLOCK_SIZE / (64 * GRANULARITY); const MAX_PAGE_COUNT: usize = 1024 * 1024 * 1024 / GRANULARITY; const TRANSLATION_TABLE_BASE_ADDR: usize = 0xFFFF_FF82_0000_0000; -pub const KERNEL_VIRTUAL_MEM_SPACE: usize = 0xFFFF_FF80_0000_0000; +#[no_mangle] +pub static KERNEL_VIRTUAL_MEM_SPACE: usize = 0xFFFF_FF80_0000_0000; pub const STACK_START_ADDR: usize = !KERNEL_VIRTUAL_MEM_SPACE & (!0xF); @@ -104,7 +105,7 @@ pub enum PhysSource { } #[repr(align(4096))] -pub struct PageTable([TableEntry; TABLE_ENTRY_COUNT]); +pub struct PageTable(pub [TableEntry; TABLE_ENTRY_COUNT]); impl Iterator for PageTable { type Item = VirtAddr; @@ -203,7 +204,6 @@ fn map_range_dynamic( (virt, _) = virt.overflowing_add(GRANULARITY); remaining -= GRANULARITY; } - Ok(()) } @@ -223,7 +223,7 @@ 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) { + if !start.is_multiple_of(LEVEL2_BLOCK_SIZE) { return Err(NovaError::Misalignment); } @@ -237,8 +237,8 @@ pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result { 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 new file mode 100644 index 0000000..646497b --- /dev/null +++ b/src/application_manager.rs @@ -0,0 +1,145 @@ +use crate::{ + aarch64::mmu::{ + find_free_kerne_page_in_block, map_page, physical_mapping::reserve_page, PageTable, + TableEntry, VirtAddr, NORMAL_MEM, TRANSLATIONTABLE_TTBR0, TRANSLATIONTABLE_TTBR1, WRITABLE, + }, + configuration::memory_mapping::{APPLICATION_TRANSLATION_TABLE_VA, EL0_STACK_TOP}, +}; +use alloc::vec::Vec; +use core::{arch::asm, mem, ptr::write_volatile}; +use log::error; +use nova_error::NovaError; +use spin::Mutex; + +struct AppManager { + apps: Option>, +} + +impl AppManager { + const fn new() -> Self { + Self { apps: None } + } +} + +unsafe impl Send for AppManager {} + +pub struct Application { + pub table_ptr: *mut TableEntry, + pub start_addr: usize, + pub stack_pointer: usize, +} + +impl Application { + pub fn new(start_addr: VirtAddr) -> Self { + let physical_addr = reserve_page(); + let virtual_address = + find_free_kerne_page_in_block(APPLICATION_TRANSLATION_TABLE_VA).unwrap(); + + map_page( + virtual_address, + physical_addr, + core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR1), + NORMAL_MEM | WRITABLE, + ) + .unwrap(); + + // TODO: Temporary solution, while kernel and app share some memory regions + #[allow(static_mut_refs)] + unsafe { + let table = &mut *(virtual_address as *mut PageTable); + table.0 = TRANSLATIONTABLE_TTBR0.0; + } + + Self { + table_ptr: physical_addr as *mut TableEntry, + start_addr, + stack_pointer: EL0_STACK_TOP, + } + } + + pub unsafe fn configure_registers(&self) { + asm!("msr ELR_EL1, {}", in(reg) self.start_addr); + asm!("msr SPSR_EL1, {0:x}", in(reg) 0); + asm!("msr SP_EL0, {0:x}", in(reg) self.stack_pointer); + asm!("msr TTBR0_EL1, {}", in(reg) self.table_ptr as usize); + } + + /// 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(&mut self, args: Vec<&str>) { + let size = args.len(); + let argv = self.construct_inital_stack(args); + unsafe { + self.configure_registers(); + asm!("", in("x0") size, in("x1") argv); + asm!("eret"); + } + } + + /// Initializes the stack based on the System V ABI + fn construct_inital_stack(&mut self, args: Vec<&str>) -> usize { + let size = args.len(); + let mut arg_addresses = Vec::with_capacity(size); + + // Write strings into stack + for value in args { + self.stack_pointer -= value.len() * mem::size_of::(); + let pointer = self.stack_pointer as *mut u8; + unsafe { core::ptr::copy(value.as_ptr(), pointer, value.len()) }; + arg_addresses.push(pointer); + } + self.stack_pointer = align_down(self.stack_pointer, 16); + + // TODO: Auxiliry vector entry + // TODO: Environment pointers + + let argv = self.stack_pointer; + + // Write argument pointers into stack + for addr in arg_addresses { + unsafe { write_volatile(self.stack_pointer as *mut *const u8, addr) }; + self.stack_pointer -= mem::size_of::<*const u8>(); + } + + argv + } +} + +fn align_down(sp: usize, align: usize) -> usize { + sp & !(align - 1) +} + +static APP_MANAGER: Mutex = Mutex::new(AppManager::new()); + +pub fn initialize_app_manager() { + let mut guard = APP_MANAGER.lock(); + guard.apps = Some(Vec::new()); +} + +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, args: Vec<&str>) -> Result<(), NovaError> { + if let Some(app) = APP_MANAGER + .lock() + .apps + .as_mut() + .and_then(|am| am.get_mut(index)) + { + app.start(args); + unreachable!() + } else { + error!("Unable to start app due to invalid App ID."); + Err(NovaError::General("Invalid app id.")) + } +} diff --git a/src/config.S b/src/config.S index 5e13a6d..ca89164 100644 --- a/src/config.S +++ b/src/config.S @@ -10,8 +10,12 @@ el2_to_el1: msr SPSR_EL2, x0 // Set return address to kernel_main + adrp x0, KERNEL_VIRTUAL_MEM_SPACE + ldr x1, [x0, :lo12:KERNEL_VIRTUAL_MEM_SPACE] + adrp x0, kernel_main add x0, x0, :lo12:kernel_main + orr x0, x0, x1 msr ELR_EL2, x0 // Set SP_EL1 to stack base @@ -74,25 +78,3 @@ configure_mmu_el1: ret -.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 - - // Set return address to el0 - ldr x0, =el0 - msr ELR_EL1, x0 - - // Set SP_EL1 to stack base - adrp x0, EL0_STACK_TOP - ldr x1, [x0, :lo12:EL0_STACK_TOP] - msr SP_EL0, x1 - - isb - - mov x0, x8 - // Return to EL0 - eret diff --git a/src/configuration/memory_mapping.rs b/src/configuration/memory_mapping.rs index 2adbcee..c6718c9 100644 --- a/src/configuration/memory_mapping.rs +++ b/src/configuration/memory_mapping.rs @@ -1,10 +1,9 @@ use crate::{ aarch64::mmu::{ - alloc_block_l2_explicit, allocate_memory, map_l2_block, map_page, - physical_mapping::reserve_page, reserve_range, PhysAddr, PhysSource, VirtAddr, DEVICE_MEM, - EL0_ACCESSIBLE, GRANULARITY, KERNEL_VIRTUAL_MEM_SPACE, LEVEL1_BLOCK_SIZE, - LEVEL2_BLOCK_SIZE, NORMAL_MEM, PXN, READ_ONLY, STACK_START_ADDR, TRANSLATIONTABLE_TTBR0, - UXN, WRITABLE, + alloc_block_l2_explicit, allocate_memory, map_page, physical_mapping::reserve_page, + reserve_range, PhysAddr, PhysSource, VirtAddr, DEVICE_MEM, EL0_ACCESSIBLE, GRANULARITY, + KERNEL_VIRTUAL_MEM_SPACE, LEVEL1_BLOCK_SIZE, LEVEL2_BLOCK_SIZE, NORMAL_MEM, PXN, READ_ONLY, + STACK_START_ADDR, TRANSLATIONTABLE_TTBR0, TRANSLATIONTABLE_TTBR1, UXN, WRITABLE, }, PERIPHERAL_BASE, }; @@ -19,6 +18,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; +// TODO: Currently limited to 512 applications, more than enough, but has to be kept +// in mind pub const APPLICATION_TRANSLATION_TABLE_VA: VirtAddr = 0xFFFF_FF81_FE00_0000; extern "C" { @@ -44,6 +45,16 @@ pub fn initialize_mmu_translation_tables() { .unwrap(); } + for addr in (0..text_end).step_by(GRANULARITY) { + map_page( + addr | KERNEL_VIRTUAL_MEM_SPACE, + addr, + core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR1), + READ_ONLY | NORMAL_MEM, + ) + .unwrap(); + } + for addr in (text_end..shared_segment_end).step_by(GRANULARITY) { map_page( addr, @@ -54,12 +65,12 @@ pub fn initialize_mmu_translation_tables() { .unwrap(); } - for addr in (shared_segment_end..kernel_end).step_by(LEVEL2_BLOCK_SIZE) { - map_l2_block( + for addr in (text_end..shared_segment_end).step_by(GRANULARITY) { + map_page( + addr | KERNEL_VIRTUAL_MEM_SPACE, addr, - addr, - core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0), - WRITABLE | UXN | NORMAL_MEM, + core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR1), + EL0_ACCESSIBLE | WRITABLE | NORMAL_MEM, ) .unwrap(); } diff --git a/src/terminal.rs b/src/console.rs similarity index 79% rename from src/terminal.rs rename to src/console.rs index f64dd33..836dec0 100644 --- a/src/terminal.rs +++ b/src/console.rs @@ -1,8 +1,7 @@ -use core::arch::asm; - use alloc::string::String; use crate::{ + application_manager::start_app, interrupt_handlers::irq::{register_interrupt_handler, IRQSource}, peripherals::uart::read_uart_data, pi3::mailbox::read_soc_temp, @@ -15,10 +14,6 @@ pub struct Terminal { input: String, } -extern "C" { - fn el1_to_el0(); -} - impl Default for Terminal { fn default() -> Self { Self::new() @@ -41,15 +36,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); - el1_to_el0(); - }, + "app" => { + if let Some(app_id) = parts.next().and_then(|a| a.parse::().ok()) { + let args = parts.collect(); + let _ = start_app(app_id, args); + } else { + println!("App ID not set."); + } + } _ => { println!("Unknown command: \"{}\"", self.input); } diff --git a/src/interrupt_handlers/synchronous.rs b/src/interrupt_handlers/synchronous.rs index 8f06c70..bf3ea55 100644 --- a/src/interrupt_handlers/synchronous.rs +++ b/src/interrupt_handlers/synchronous.rs @@ -20,12 +20,16 @@ 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!("Data Abort from a lower Exception level"); + error!("Cause: {}", decode_data_abort(esr.iss as usize)); } 0b010101 => { - debug!("Cause: SVC instruction execution in AArch64"); + debug!("SVC instruction execution in AArch64"); return handle_svc(frame); } + 0b100010 => { + error!("PC alignment fault."); + } _ => { error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec); } @@ -36,8 +40,62 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr 0 } +fn decode_data_abort(iss: usize) -> &'static str { + match iss & 0b111111 { + 0b000000 => "Address size fault, level 0", + 0b000001 => "Address size fault, level 1", + 0b000010 => "Address size fault, level 2", + 0b000011 => "Address size fault, level 3", + + 0b000100 => "Translation fault, level 0", + 0b000101 => "Translation fault, level 1", + 0b000110 => "Translation fault, level 2", + 0b000111 => "Translation fault, level 3", + + 0b001001 => "Access flag fault, level 1", + 0b001010 => "Access flag fault, level 2", + 0b001011 => "Access flag fault, level 3", + + 0b001101 => "Permission fault, level 1", + 0b001110 => "Permission fault, level 2", + 0b001111 => "Permission fault, level 3", + + 0b010000 => "Synchronous External abort, not on translation table walk", + 0b011000 => { + "Synchronous parity or ECC error on memory access, not on translation table walk" + } + + 0b010100 => "Synchronous External abort, on translation table walk, level 0", + 0b010101 => "Synchronous External abort, on translation table walk, level 1", + 0b010110 => "Synchronous External abort, on translation table walk, level 2", + 0b010111 => "Synchronous External abort, on translation table walk, level 3", + + 0b011100 => "Synchronous parity or ECC error on translation table walk, level 0", + 0b011101 => "Synchronous parity or ECC error on translation table walk, level 1", + 0b011110 => "Synchronous parity or ECC error on translation table walk, level 2", + 0b011111 => "Synchronous parity or ECC error on translation table walk, level 3", + + 0b100001 => "Alignment fault", + 0b110000 => "TLB conflict abort", + 0b110001 => "Unsupported atomic hardware update fault", + + 0b110100 => "IMPLEMENTATION DEFINED fault (Lockdown)", + 0b110101 => "IMPLEMENTATION DEFINED fault (Unsupported Exclusive or Atomic access)", + + 0b111101 => "Section Domain Fault", + 0b111110 => "Page Domain Fault", + + _ => "Reserved / Unknown", + } +} + fn handle_svc(frame: &mut TrapFrame) -> usize { match frame.x8 { + 0 => { + debug!("Program exited!"); + set_return_to_kernel_loop(); + 0 + } 67 => { let response = mailbox::read_soc_temp([0]).unwrap(); response[1] as usize diff --git a/src/lib.rs b/src/lib.rs index 25b0865..63b489d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,10 @@ use crate::{ allocate_memory, PhysSource, KERNEL_VIRTUAL_MEM_SPACE, LEVEL2_BLOCK_SIZE, NORMAL_MEM, UXN, WRITABLE, }, + application_manager::initialize_app_manager, + console::{flush_terminal, init_terminal}, interrupt_handlers::irq::initialize_interrupt_handler, pi3::timer::sleep_s, - terminal::{flush_terminal, init_terminal}, }; static LOGGER: UartLogger = UartLogger; @@ -57,8 +58,9 @@ pub mod configuration; pub mod framebuffer; pub mod interrupt_handlers; +pub mod application_manager; +pub mod console; pub mod pi3; -pub mod terminal; #[inline(always)] pub unsafe fn read_address(address: u32) -> u32 { @@ -85,6 +87,7 @@ pub fn get_current_el() -> u64 { pub fn initialize_kernel() { unsafe { initialize_kernel_heap() }; initialize_interrupt_handler(); + initialize_app_manager(); init_terminal(); } diff --git a/src/main.rs b/src/main.rs index 0b1d814..5702781 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,9 +10,10 @@ use log::{debug, info}; extern crate alloc; -use alloc::vec::Vec; +use alloc::{slice, vec::Vec}; use nova::{ aarch64::registers::{daif, read_id_aa64mmfr0_el1}, + application_manager::{add_app, Application}, configuration::memory_mapping::initialize_mmu_translation_tables, framebuffer::{FrameBuffer, BLUE, GREEN, RED}, get_current_el, init_logger, @@ -24,6 +25,7 @@ use nova::{ }, uart::uart_init, }, + pi3::timer::sleep_s, print, println, }; @@ -77,7 +79,6 @@ pub extern "C" fn main() -> ! { unsafe { el2_to_el1(); } - #[allow(clippy::empty_loop)] loop {} } @@ -101,23 +102,40 @@ pub extern "C" fn kernel_main() { test_vector.push(i); } debug!("heap allocation test: {:?}", test_vector); - enable_irq_source(IRQSource::UartInt); + let app = Application::new(el0 as *const () as usize); + add_app(app).unwrap(); + 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(input: usize) { +pub unsafe extern "C" fn el0(argc: usize, argv: *const *const u8) { println!("Jumped into EL0"); + println!("num: {}", argc); + println!("argv: {:?}", argv); + + let raw_args = unsafe { slice::from_raw_parts(argv, argc) }; + let first_arg = raw_args + .iter() + .map(|&arg_ptr| { + if arg_ptr.is_null() { + return ""; + } + + let c_str = unsafe { core::ffi::CStr::from_ptr(arg_ptr) }; + let str_slice = c_str.to_str().unwrap(); + str_slice + }) + .next(); + + sleep_s(1); // Set GPIO 26 to Input enable_irq_source(IRQSource::GpioInt0); //26 is on the first GPIO bank @@ -140,25 +158,30 @@ pub extern "C" fn el0(input: usize) { let _temp = syscall(67); - println!("Calculting prime to: {}", input); + if let Some(num) = first_arg.and_then(|val| val.parse::().ok()) { + println!("Calculting prime to: {}", num); - for i in 3..input { - let mut is_prime = true; - for j in 3..i { - if i == j { - continue; + for i in 3..num { + let mut is_prime = true; + for j in 3..i { + if i == j { + continue; + } + if i % j == 0 { + is_prime = false; + } } - if i % j == 0 { - is_prime = false; + if is_prime { + print!("{} ", i); } } - if is_prime { - print!("{} ", i); - } + println!(""); + } else { + println!("Input NaN"); } - println!(""); blink_gpio(SpecificGpio::OnboardLed as u8, 500); + syscall(0); } fn cos(x: u32) -> f64 { diff --git a/tools/start_simulator_debug.sh b/tools/start_simulator_debug.sh index 9f52332..b9a70df 100755 --- a/tools/start_simulator_debug.sh +++ b/tools/start_simulator_debug.sh @@ -11,4 +11,4 @@ qemu-system-aarch64 \ -cpu cortex-a53 \ -serial stdio \ -sd ../sd.img \ - -kernel ../target/aarch64-unknown-none/debug/kernel8.img \ + -kernel ../target/aarch64-unknown-none/debug/kernel8.img -S -s diff --git a/workspace/heap/src/tests.rs b/workspace/heap/src/tests.rs index cad2fd2..c5cb0af 100644 --- a/workspace/heap/src/tests.rs +++ b/workspace/heap/src/tests.rs @@ -29,7 +29,7 @@ fn test_heap_allocation() { assert_eq!(actual_alloc_size % MIN_BLOCK_SIZE, 0); // Verify section is occupied - assert!((*malloc_header).free == false); + assert!(!(*malloc_header).free); // Verify next header has been created let next = (*malloc_header).next.unwrap(); @@ -55,7 +55,7 @@ fn test_full_heap() { let malloc = heap.malloc(malloc_size).unwrap(); let malloc_header = Heap::get_header_ref_from_data_pointer(malloc); unsafe { - assert_eq!((*malloc_header).free, false); + assert!(!(*malloc_header).free); assert!((*malloc_header).next.is_none()); } @@ -79,7 +79,7 @@ fn test_freeing_root() { let malloc = heap.malloc(malloc_size).unwrap(); let malloc_header = Heap::get_header_ref_from_data_pointer(malloc); unsafe { - assert_eq!((*malloc_header).free, false); + assert!(!(*malloc_header).free); assert!((*malloc_header).size >= malloc_size); assert!((*root_header).next.is_some()); 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, }