From 778b3ed80c6fa7cafc714992268752de8f5db1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Neuh=C3=A4user?= Date: Thu, 19 Mar 2026 10:43:45 +0100 Subject: [PATCH] feat: move EL0 stack to virtual space --- link.ld | 18 +++++-------- src/aarch64/mmu.rs | 19 +++++--------- src/config.S | 5 ++-- src/configuration.rs | 61 +++++++++++++++++++++++++++++--------------- src/main.rs | 46 +++++++++++++++------------------ 5 files changed, 76 insertions(+), 73 deletions(-) diff --git a/link.ld b/link.ld index 548260b..747c275 100644 --- a/link.ld +++ b/link.ld @@ -4,14 +4,15 @@ SECTIONS { .text ALIGN(4) : { KEEP(*(.text._start)) *(.text .text.*) + . = ALIGN(4K); + __text_end = .; } .rodata : { *(.rodata .rodata.*) } - .data ALIGN(2M) : { - _data = .; + .data : { *(.data .data.*) } @@ -21,6 +22,10 @@ SECTIONS { __bss_end = .; } + . = ALIGN(2M); + + __share_end = .; + .vector_table ALIGN(2K) : { KEEP(*(.vector_table)) } @@ -36,15 +41,6 @@ SECTIONS { . = ALIGN(2M); __kernel_end = .; - - .stack_el0 : { - __stack_start_el0 = .; - . += 10K; #10kB stack - __stack_end_el0 = .; - } - - . = ALIGN(2M); - _end = .; } __bss_size = (__bss_end - __bss_start) >> 3; diff --git a/src/aarch64/mmu.rs b/src/aarch64/mmu.rs index 2bdd297..9063960 100644 --- a/src/aarch64/mmu.rs +++ b/src/aarch64/mmu.rs @@ -8,13 +8,6 @@ use crate::{ get_current_el, }; -unsafe extern "C" { - static mut __translation_table_l2_start: u64; - static __stack_start_el0: u64; - static __kernel_end: u64; - static _data: u64; -} - const BLOCK: u64 = 0b01; const TABLE: u64 = 0b11; const PAGE: u64 = 0b11; @@ -111,21 +104,21 @@ fn map_range_explicit( while virt % LEVEL2_BLOCK_SIZE != 0 { map_page(virt, phys, base, flags)?; - virt += GRANULARITY; + (virt, _) = virt.overflowing_add(GRANULARITY); phys += GRANULARITY; remaining -= GRANULARITY; } while remaining >= LEVEL2_BLOCK_SIZE { map_l2_block(virt, phys, base, flags)?; - virt += LEVEL2_BLOCK_SIZE; + (virt, _) = virt.overflowing_add(LEVEL2_BLOCK_SIZE); phys += LEVEL2_BLOCK_SIZE; remaining -= LEVEL2_BLOCK_SIZE; } while remaining > 0 { map_page(virt, phys, base, flags)?; - virt += GRANULARITY; + (virt, _) = virt.overflowing_add(GRANULARITY); phys += GRANULARITY; remaining -= GRANULARITY; } @@ -143,13 +136,13 @@ fn map_range_dynamic( while remaining >= LEVEL2_BLOCK_SIZE { map_l2_block(virt, reserve_block(), base, flags)?; - virt += LEVEL2_BLOCK_SIZE; + (virt, _) = virt.overflowing_add(LEVEL2_BLOCK_SIZE); remaining -= LEVEL2_BLOCK_SIZE; } while remaining > 0 { map_page(virt, reserve_page(), base, flags)?; - virt += GRANULARITY; + (virt, _) = virt.overflowing_add(GRANULARITY); remaining -= GRANULARITY; } @@ -186,7 +179,7 @@ pub fn alloc_page_explicit( ) } -fn map_page( +pub fn map_page( virtual_address: usize, physical_address: usize, base_table_ptr: *mut PageTable, diff --git a/src/config.S b/src/config.S index 05f69b1..d544e6d 100644 --- a/src/config.S +++ b/src/config.S @@ -87,8 +87,9 @@ el1_to_el0: msr ELR_EL1, x0 // Set SP_EL1 to stack base - ldr x0, =__stack_end_el0 - msr SP_EL0, x0 + adrp x0, EL0_STACK_TOP + ldr x1, [x0, :lo12:EL0_STACK_TOP] + msr SP_EL0, x1 isb diff --git a/src/configuration.rs b/src/configuration.rs index 8f2b250..949eede 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -34,9 +34,9 @@ pub static TCR_EL1_CONF: u64 = IPS | TG0 | TG1 | T0SZ | T1SZ | SH0 | SH1 | AS; pub mod mmu { use crate::{ aarch64::mmu::{ - alloc_block_l2_explicit, allocate_memory, map_l2_block, reserve_range, PhysSource, - DEVICE_MEM, EL0_ACCESSIBLE, KERNEL_VIRTUAL_MEM_SPACE, LEVEL1_BLOCK_SIZE, - LEVEL2_BLOCK_SIZE, NORMAL_MEM, PXN, READ_ONLY, STACK_START_ADDR, + alloc_block_l2_explicit, allocate_memory, map_l2_block, map_page, reserve_range, + PhysSource, 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, }, PERIPHERAL_BASE, @@ -45,22 +45,24 @@ pub mod mmu { #[no_mangle] static EL1_STACK_TOP: usize = STACK_START_ADDR | KERNEL_VIRTUAL_MEM_SPACE; const EL1_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2; - + #[no_mangle] + static EL0_STACK_TOP: usize = STACK_START_ADDR; + const EL0_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2; extern "C" { - static _data: u64; - static _end: u64; + static __text_end: u64; + static __share_end: u64; static __kernel_end: u64; } pub fn initialize_mmu_translation_tables() { - let shared_segment_end = unsafe { &_data } as *const _ as usize; + let text_end = unsafe { &__text_end } as *const _ as usize; + let shared_segment_end = unsafe { &__share_end } as *const _ as usize; let kernel_end = unsafe { &__kernel_end } as *const _ as usize; - let user_space_end = unsafe { &_end } as *const _ as usize; - reserve_range(0x0, user_space_end).unwrap(); + reserve_range(0x0, kernel_end).unwrap(); - for addr in (0..shared_segment_end).step_by(LEVEL2_BLOCK_SIZE) { - map_l2_block( + for addr in (0..text_end).step_by(GRANULARITY) { + map_page( addr, addr, core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0), @@ -69,6 +71,16 @@ pub mod mmu { .unwrap(); } + for addr in (text_end..shared_segment_end).step_by(GRANULARITY) { + map_page( + addr, + addr, + core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0), + EL0_ACCESSIBLE | WRITABLE | NORMAL_MEM, + ) + .unwrap(); + } + for addr in (shared_segment_end..kernel_end).step_by(LEVEL2_BLOCK_SIZE) { map_l2_block( addr, @@ -79,16 +91,6 @@ pub mod mmu { .unwrap(); } - for addr in (kernel_end..user_space_end).step_by(LEVEL2_BLOCK_SIZE) { - map_l2_block( - addr, - addr, - core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0), - EL0_ACCESSIBLE | WRITABLE | PXN | NORMAL_MEM, - ) - .unwrap(); - } - for addr in (PERIPHERAL_BASE..LEVEL1_BLOCK_SIZE).step_by(LEVEL2_BLOCK_SIZE) { alloc_block_l2_explicit( addr, @@ -99,6 +101,15 @@ pub mod mmu { .unwrap(); } + // Frame Buffer memory range + allocate_memory( + 0x3c100000, + 1080 * 1920 * 4, + PhysSource::Explicit(0x3c100000), + NORMAL_MEM | PXN | UXN | WRITABLE | EL0_ACCESSIBLE, + ) + .unwrap(); + allocate_memory( EL1_STACK_TOP - EL1_STACK_SIZE + 0x10, EL1_STACK_SIZE, @@ -106,5 +117,13 @@ pub mod mmu { WRITABLE | NORMAL_MEM, ) .unwrap(); + + allocate_memory( + EL0_STACK_TOP - EL0_STACK_SIZE + 0x10, + EL0_STACK_SIZE, + PhysSource::Any, + WRITABLE | EL0_ACCESSIBLE | NORMAL_MEM, + ) + .unwrap(); } } diff --git a/src/main.rs b/src/main.rs index 25d07b0..5a82d0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,10 +11,7 @@ extern crate alloc; use alloc::vec::Vec; use nova::{ - aarch64::{ - mmu::{allocate_memory, PhysSource, EL0_ACCESSIBLE, NORMAL_MEM, PXN, UXN, WRITABLE}, - registers::{daif, read_id_aa64mmfr0_el1}, - }, + aarch64::registers::{daif, read_id_aa64mmfr0_el1}, configuration::mmu::initialize_mmu_translation_tables, framebuffer::{FrameBuffer, BLUE, GREEN, RED}, get_current_el, @@ -26,13 +23,14 @@ use nova::{ }, uart::uart_init, }, - pi3::mailbox, println, }; global_asm!(include_str!("vector.S")); global_asm!(include_str!("config.S")); +static mut FRAMEBUFFER: Option = None; + extern "C" { fn el2_to_el1(); fn el1_to_el0(); @@ -74,6 +72,8 @@ pub extern "C" fn main() -> ! { println!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1()); println!("Moving El2->EL1"); + unsafe { FRAMEBUFFER = Some(FrameBuffer::default()) }; + unsafe { el2_to_el1(); } @@ -100,15 +100,6 @@ pub extern "C" fn kernel_main() -> ! { } println!("heap allocation test: {:?}", test_vector); - // Frame Buffer memory range - // TODO: this is just temporary - allocate_memory( - 0x3c100000, - 1080 * 1920 * 4, - PhysSource::Explicit(0x3c100000), - NORMAL_MEM | PXN | UXN | WRITABLE | EL0_ACCESSIBLE, - ) - .unwrap(); println!("Exception Level: {}", get_current_el()); daif::unmask_all(); @@ -132,22 +123,25 @@ pub extern "C" fn el0() -> ! { enable_irq_source(IRQSource::UartInt); - let fb = FrameBuffer::default(); + if let Some(fb) = unsafe { FRAMEBUFFER.as_mut() } { + for i in 0..1080 { + fb.draw_pixel(50, i, BLUE); + } + fb.draw_square(500, 500, 600, 700, RED); + fb.draw_square_fill(800, 800, 900, 900, GREEN); + fb.draw_square_fill(1000, 800, 1200, 700, BLUE); + fb.draw_square_fill(900, 100, 800, 150, RED | BLUE); + fb.draw_string("Hello World! :D\nTest next Line", 500, 5, 3, BLUE); - for i in 0..1080 { - fb.draw_pixel(50, i, BLUE); + fb.draw_function(cos, 0, 101, RED); } - fb.draw_square(500, 500, 600, 700, RED); - fb.draw_square_fill(800, 800, 900, 900, GREEN); - fb.draw_square_fill(1000, 800, 1200, 700, BLUE); - fb.draw_square_fill(900, 100, 800, 150, RED | BLUE); - fb.draw_string("Hello World! :D\nTest next Line", 500, 5, 3, BLUE); - - fb.draw_function(cos, 0, 101, RED); loop { - let temp = mailbox::read_soc_temp([0]).unwrap(); - println!("{} °C", temp[1] / 1000); + // TODO: Mailbox requires a physical address. The stack is now in VA space causing an issue. + // Fix with SVCs ? + + // let temp = mailbox::read_soc_temp([0]).unwrap(); + // println!("{} °C", temp[1] / 1000); blink_gpio(SpecificGpio::OnboardLed as u8, 500); }