From 618048e0e3f990a73284cde171a322bf9b48642d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 9 Jun 2026 17:27:42 +0200 Subject: [PATCH 01/15] refactor: replace addr_of_mut! with &raw mut --- src/arch/aarch64/mod.rs | 25 ++++++++++++------------- src/arch/riscv64/start.rs | 3 +-- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 775cd609..6d13f66b 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -118,45 +118,44 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { let uart_address: u32 = CONSOLE.lock().get().get_stdout(); info!("Detect UART at {uart_address:#x}"); - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l0_pgtable), 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l0_pgtable, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = ptr::addr_of_mut!(l1_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[511] = ptr::addr_of_mut!(l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; + pgt_slice[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l1_pgtable), 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l1_pgtable, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = ptr::addr_of_mut!(l2_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[1] = ptr::addr_of_mut!(l2k_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l2_pgtable), 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2_pgtable, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = ptr::addr_of_mut!(l3_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l3_pgtable), 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l3_pgtable, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } pgt_slice[1] = uart_address as u64 + PT_MEM_CD; // map kernel to __executable_start and stack below the kernel - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(l2k_pgtable), 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2k_pgtable, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) { - *pgt_slice = ptr::addr_of_mut!(L0mib_pgtable).expose_provenance() as u64 + *pgt_slice = (&raw mut L0mib_pgtable).expose_provenance() as u64 + (i * BasePageSize::SIZE) as u64 + PT_PT; } - let pgt_slice = - unsafe { core::slice::from_raw_parts_mut(ptr::addr_of_mut!(L0mib_pgtable), 10 * 512) }; + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut L0mib_pgtable, 10 * 512) }; for (i, entry) in pgt_slice.iter_mut().enumerate() { *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; } diff --git a/src/arch/riscv64/start.rs b/src/arch/riscv64/start.rs index 2abed533..98584fce 100644 --- a/src/arch/riscv64/start.rs +++ b/src/arch/riscv64/start.rs @@ -21,8 +21,7 @@ pub fn get_fdt() -> Fdt<'static> { } pub fn get_stack_ptr() -> *mut u8 { - // SAFETY: We only create a pointer here - let stack_top = ptr::addr_of_mut!(STACK); + let stack_top = &raw mut STACK; // SAFETY: Pointing directly past the object is allowed let stack_bottom = unsafe { stack_top.add(1) }; stack_bottom.cast::() From 42175d00be75dfb7d05e99affe6fe2823a981561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 9 Jun 2026 18:39:12 +0200 Subject: [PATCH 02/15] refactor(aarch64): extract page tables into module --- src/arch/aarch64/mod.rs | 76 +++---------------------------- src/arch/aarch64/page_tables.rs | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 69 deletions(-) create mode 100644 src/arch/aarch64/page_tables.rs diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 6d13f66b..5b10c9e7 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -3,13 +3,13 @@ mod console; pub use self::console::Console; pub mod drivers; pub mod entry; +mod page_tables; pub mod paging; use core::arch::asm; use core::ptr; -use aarch64_cpu::asm::barrier::{self, NSH, SY, dmb, dsb, isb}; -use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable}; +use aarch64_cpu::asm::barrier::{NSH, SY, dmb, dsb, isb}; use align_address::Align; use fdt::Fdt; use goblin::elf::header::header64::{EI_DATA, ELFDATA2LSB, ELFMAG, Header, SELFMAG}; @@ -22,15 +22,6 @@ use crate::BootInfoExt; use crate::arch::paging::*; use crate::os::CONSOLE; -unsafe extern "C" { - static mut l0_pgtable: u64; - static mut l1_pgtable: u64; - static mut l2_pgtable: u64; - static mut l2k_pgtable: u64; - static mut l3_pgtable: u64; - static mut L0mib_pgtable: u64; -} - /// start address of the RAM at Qemu's virt emulation const RAM_START: u64 = 0x40000000; /// Default stack size of the kernel @@ -40,13 +31,6 @@ const KERNEL_STACK_SIZE: usize = 32_768; /// see const DEVICE_TREE: u64 = RAM_START; -#[allow(dead_code)] -const PT_DEVICE: u64 = 0x707; -const PT_PT: u64 = 0x713; -const PT_MEM: u64 = 0x713; -const PT_MEM_CD: u64 = 0x70F; -const PT_SELF: u64 = 1 << 55; - pub unsafe fn get_memory(_memory_size: u64) -> u64 { let loader_end = crate::os::executable_end().as_ptr(); (loader_end.expose_provenance() as u64).align_up(LargePageSize::SIZE as u64) @@ -118,61 +102,15 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { let uart_address: u32 = CONSOLE.lock().get().get_stdout(); info!("Detect UART at {uart_address:#x}"); - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l0_pgtable, 512) }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; - - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l1_pgtable, 512) }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; - - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2_pgtable, 512) }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; - - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l3_pgtable, 512) }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[1] = uart_address as u64 + PT_MEM_CD; - - // map kernel to __executable_start and stack below the kernel - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2k_pgtable, 512) }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) { - *pgt_slice = (&raw mut L0mib_pgtable).expose_provenance() as u64 - + (i * BasePageSize::SIZE) as u64 - + PT_PT; - } - - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut L0mib_pgtable, 10 * 512) }; - for (i, entry) in pgt_slice.iter_mut().enumerate() { - *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; + unsafe { + page_tables::init(uart_address); } CONSOLE.lock().get().set_stdout(0x1000); - // Load TTBRx - TTBR1_EL1.set(0); - TTBR0_EL1.set(&raw mut l0_pgtable as u64); - barrier::dsb(barrier::SY); - barrier::isb(barrier::SY); - - // Enable paging - SCTLR_EL1.modify(SCTLR_EL1::M::Enable); - barrier::isb(barrier::SY); - - info!("Successfully set up paging."); + unsafe { + page_tables::enable(); + } let fdt = unsafe { Fdt::from_ptr(ptr::with_exposed_provenance(DEVICE_TREE as usize)) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs new file mode 100644 index 00000000..b751be56 --- /dev/null +++ b/src/arch/aarch64/page_tables.rs @@ -0,0 +1,80 @@ +use aarch64_cpu::asm::barrier; +use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable}; +use log::info; + +use super::RAM_START; +use super::paging::{BasePageSize, PageSize}; + +unsafe extern "C" { + static mut l0_pgtable: u64; + static mut l1_pgtable: u64; + static mut l2_pgtable: u64; + static mut l2k_pgtable: u64; + static mut l3_pgtable: u64; + static mut L0mib_pgtable: u64; +} + +#[allow(dead_code)] +const PT_DEVICE: u64 = 0x707; +const PT_PT: u64 = 0x713; +const PT_MEM: u64 = 0x713; +const PT_MEM_CD: u64 = 0x70F; +const PT_SELF: u64 = 1 << 55; + +pub unsafe fn init(uart_address: u32) { + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l0_pgtable, 512) }; + for i in pgt_slice.iter_mut() { + *i = 0; + } + pgt_slice[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; + + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l1_pgtable, 512) }; + for i in pgt_slice.iter_mut() { + *i = 0; + } + pgt_slice[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; + pgt_slice[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; + + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2_pgtable, 512) }; + for i in pgt_slice.iter_mut() { + *i = 0; + } + pgt_slice[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; + + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l3_pgtable, 512) }; + for i in pgt_slice.iter_mut() { + *i = 0; + } + pgt_slice[1] = uart_address as u64 + PT_MEM_CD; + + // map kernel to __executable_start and stack below the kernel + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2k_pgtable, 512) }; + for i in pgt_slice.iter_mut() { + *i = 0; + } + for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) { + *pgt_slice = (&raw mut L0mib_pgtable).expose_provenance() as u64 + + (i * BasePageSize::SIZE) as u64 + + PT_PT; + } + + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut L0mib_pgtable, 10 * 512) }; + for (i, entry) in pgt_slice.iter_mut().enumerate() { + *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; + } +} + +pub unsafe fn enable() { + // Load TTBRx + TTBR1_EL1.set(0); + TTBR0_EL1.set(&raw mut l0_pgtable as u64); + barrier::dsb(barrier::SY); + barrier::isb(barrier::SY); + + // Enable paging + SCTLR_EL1.modify(SCTLR_EL1::M::Enable); + barrier::isb(barrier::SY); + + info!("Successfully set up paging."); +} From b89c1855ffdc057a1c598934b2232422ed54d332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 11 Jun 2026 11:01:00 +0200 Subject: [PATCH 03/15] fix(aarch64): lossy_provenance_casts --- src/arch/aarch64/page_tables.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index b751be56..c764ee39 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -68,7 +68,7 @@ pub unsafe fn init(uart_address: u32) { pub unsafe fn enable() { // Load TTBRx TTBR1_EL1.set(0); - TTBR0_EL1.set(&raw mut l0_pgtable as u64); + TTBR0_EL1.set((&raw mut l0_pgtable).expose_provenance() as u64); barrier::dsb(barrier::SY); barrier::isb(barrier::SY); From 154994924ce88c6f67166f39a116add5b635dc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 10 Jun 2026 15:23:24 +0200 Subject: [PATCH 04/15] refactor(aarch64): paging::enable --- src/arch/aarch64/page_tables.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index c764ee39..22f0a804 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -1,4 +1,4 @@ -use aarch64_cpu::asm::barrier; +use aarch64_cpu::asm::barrier::{SY, dsb, isb}; use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable}; use log::info; @@ -66,15 +66,15 @@ pub unsafe fn init(uart_address: u32) { } pub unsafe fn enable() { - // Load TTBRx + // Set Translation Table Base Registers (TTBR) TTBR1_EL1.set(0); TTBR0_EL1.set((&raw mut l0_pgtable).expose_provenance() as u64); - barrier::dsb(barrier::SY); - barrier::isb(barrier::SY); + dsb(SY); + isb(SY); - // Enable paging + // Set MMU enable in System Control Register (SCTLR) SCTLR_EL1.modify(SCTLR_EL1::M::Enable); - barrier::isb(barrier::SY); + isb(SY); info!("Successfully set up paging."); } From d762b683aac4b3f3d236ccbb47bb2e174a60e16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 9 Jun 2026 18:28:59 +0200 Subject: [PATCH 05/15] fix(aarch64): dead_code --- src/arch/aarch64/page_tables.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 22f0a804..24af9556 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -14,8 +14,6 @@ unsafe extern "C" { static mut L0mib_pgtable: u64; } -#[allow(dead_code)] -const PT_DEVICE: u64 = 0x707; const PT_PT: u64 = 0x713; const PT_MEM: u64 = 0x713; const PT_MEM_CD: u64 = 0x70F; From 139420d0a1ee4d1c8de73ff33c7610ddf48bbfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 9 Jun 2026 17:23:28 +0200 Subject: [PATCH 06/15] refactor(aarch64): address Lxmib_pagetables independently --- src/arch/aarch64/entry.s | 9 ++++++++ src/arch/aarch64/page_tables.rs | 39 ++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/arch/aarch64/entry.s b/src/arch/aarch64/entry.s index 14e870ba..a7c9f80a 100644 --- a/src/arch/aarch64/entry.s +++ b/src/arch/aarch64/entry.s @@ -88,6 +88,15 @@ el_1_entry: .global l2k_pgtable .global l3_pgtable .global L0mib_pgtable +.global L2mib_pgtable +.global L4mib_pgtable +.global L6mib_pgtable +.global L8mib_pgtable +.global L10mib_pgtable +.global L12mib_pgtable +.global L14mib_pgtable +.global L16mib_pgtable +.global L18mib_pgtable .align 12 l0_pgtable: diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 24af9556..fde5b911 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -12,6 +12,15 @@ unsafe extern "C" { static mut l2k_pgtable: u64; static mut l3_pgtable: u64; static mut L0mib_pgtable: u64; + static mut L2mib_pgtable: u64; + static mut L4mib_pgtable: u64; + static mut L6mib_pgtable: u64; + static mut L8mib_pgtable: u64; + static mut L10mib_pgtable: u64; + static mut L12mib_pgtable: u64; + static mut L14mib_pgtable: u64; + static mut L16mib_pgtable: u64; + static mut L18mib_pgtable: u64; } const PT_PT: u64 = 0x713; @@ -51,15 +60,29 @@ pub unsafe fn init(uart_address: u32) { for i in pgt_slice.iter_mut() { *i = 0; } - for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) { - *pgt_slice = (&raw mut L0mib_pgtable).expose_provenance() as u64 - + (i * BasePageSize::SIZE) as u64 - + PT_PT; - } - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut L0mib_pgtable, 10 * 512) }; - for (i, entry) in pgt_slice.iter_mut().enumerate() { - *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; + let mib_pgtables = [ + &raw mut L0mib_pgtable, + &raw mut L2mib_pgtable, + &raw mut L4mib_pgtable, + &raw mut L6mib_pgtable, + &raw mut L8mib_pgtable, + &raw mut L10mib_pgtable, + &raw mut L12mib_pgtable, + &raw mut L14mib_pgtable, + &raw mut L16mib_pgtable, + &raw mut L18mib_pgtable, + ]; + + for (mib_i, mib_pgtable) in mib_pgtables.into_iter().enumerate() { + pgt_slice[mib_i] = mib_pgtable as u64 + PT_PT; + + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(mib_pgtable, 512) }; + + for (i, entry) in pgt_slice.iter_mut().enumerate() { + let i = mib_i * 512 + i; + *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; + } } } From a98912769233ac66a686602e859a9f65ad787c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 9 Jun 2026 17:36:05 +0200 Subject: [PATCH 07/15] refactor(aarch64): give page table types the right size --- src/arch/aarch64/mod.rs | 1 + src/arch/aarch64/page_tables.rs | 99 +++++++++++++++++---------------- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 5b10c9e7..f71e63ca 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -86,6 +86,7 @@ pub fn find_kernel() -> &'static [u8] { } } +#[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { let LoadedKernel { load_info, diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index fde5b911..d1a20ee9 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -1,3 +1,5 @@ +use core::ptr; + use aarch64_cpu::asm::barrier::{SY, dsb, isb}; use aarch64_cpu::registers::{ReadWriteable, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1, Writeable}; use log::info; @@ -6,21 +8,21 @@ use super::RAM_START; use super::paging::{BasePageSize, PageSize}; unsafe extern "C" { - static mut l0_pgtable: u64; - static mut l1_pgtable: u64; - static mut l2_pgtable: u64; - static mut l2k_pgtable: u64; - static mut l3_pgtable: u64; - static mut L0mib_pgtable: u64; - static mut L2mib_pgtable: u64; - static mut L4mib_pgtable: u64; - static mut L6mib_pgtable: u64; - static mut L8mib_pgtable: u64; - static mut L10mib_pgtable: u64; - static mut L12mib_pgtable: u64; - static mut L14mib_pgtable: u64; - static mut L16mib_pgtable: u64; - static mut L18mib_pgtable: u64; + static mut l0_pgtable: [u64; 512]; + static mut l1_pgtable: [u64; 512]; + static mut l2_pgtable: [u64; 512]; + static mut l2k_pgtable: [u64; 512]; + static mut l3_pgtable: [u64; 512]; + static mut L0mib_pgtable: [u64; 512]; + static mut L2mib_pgtable: [u64; 512]; + static mut L4mib_pgtable: [u64; 512]; + static mut L6mib_pgtable: [u64; 512]; + static mut L8mib_pgtable: [u64; 512]; + static mut L10mib_pgtable: [u64; 512]; + static mut L12mib_pgtable: [u64; 512]; + static mut L14mib_pgtable: [u64; 512]; + static mut L16mib_pgtable: [u64; 512]; + static mut L18mib_pgtable: [u64; 512]; } const PT_PT: u64 = 0x713; @@ -28,58 +30,59 @@ const PT_MEM: u64 = 0x713; const PT_MEM_CD: u64 = 0x70F; const PT_SELF: u64 = 1 << 55; +#[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l0_pgtable, 512) }; - for i in pgt_slice.iter_mut() { + let pgt = unsafe { &mut l0_pgtable }; + for i in pgt.iter_mut() { *i = 0; } - pgt_slice[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; + pgt[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; + pgt[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l1_pgtable, 512) }; - for i in pgt_slice.iter_mut() { + let pgt = unsafe { &mut l1_pgtable }; + for i in pgt.iter_mut() { *i = 0; } - pgt_slice[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; - pgt_slice[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; + pgt[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; + pgt[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2_pgtable, 512) }; - for i in pgt_slice.iter_mut() { + let pgt = unsafe { &mut l2_pgtable }; + for i in pgt.iter_mut() { *i = 0; } - pgt_slice[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; + pgt[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l3_pgtable, 512) }; - for i in pgt_slice.iter_mut() { + let pgt = unsafe { &mut l3_pgtable }; + for i in pgt.iter_mut() { *i = 0; } - pgt_slice[1] = uart_address as u64 + PT_MEM_CD; + pgt[1] = uart_address as u64 + PT_MEM_CD; // map kernel to __executable_start and stack below the kernel - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&raw mut l2k_pgtable, 512) }; - for i in pgt_slice.iter_mut() { + let pgt = unsafe { &mut l2k_pgtable }; + for i in pgt.iter_mut() { *i = 0; } - let mib_pgtables = [ - &raw mut L0mib_pgtable, - &raw mut L2mib_pgtable, - &raw mut L4mib_pgtable, - &raw mut L6mib_pgtable, - &raw mut L8mib_pgtable, - &raw mut L10mib_pgtable, - &raw mut L12mib_pgtable, - &raw mut L14mib_pgtable, - &raw mut L16mib_pgtable, - &raw mut L18mib_pgtable, - ]; - - for (mib_i, mib_pgtable) in mib_pgtables.into_iter().enumerate() { - pgt_slice[mib_i] = mib_pgtable as u64 + PT_PT; + let mib_pgtables = unsafe { + [ + &mut L0mib_pgtable, + &mut L2mib_pgtable, + &mut L4mib_pgtable, + &mut L6mib_pgtable, + &mut L8mib_pgtable, + &mut L10mib_pgtable, + &mut L12mib_pgtable, + &mut L14mib_pgtable, + &mut L16mib_pgtable, + &mut L18mib_pgtable, + ] + }; - let pgt_slice = unsafe { core::slice::from_raw_parts_mut(mib_pgtable, 512) }; + for (mib_i, mib_pgt) in mib_pgtables.into_iter().enumerate() { + pgt[mib_i] = ptr::from_mut(mib_pgt) as u64 + PT_PT; - for (i, entry) in pgt_slice.iter_mut().enumerate() { + for (i, entry) in mib_pgt.iter_mut().enumerate() { let i = mib_i * 512 + i; *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; } From 574c6e1b0745ebe9e77b5e09e3d65ad1f93bc20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 10 Jun 2026 10:12:13 +0200 Subject: [PATCH 08/15] refactor(aarch64): use pointers in page tables --- src/arch/aarch64/page_tables.rs | 76 ++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index d1a20ee9..f94d3a27 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -8,60 +8,64 @@ use super::RAM_START; use super::paging::{BasePageSize, PageSize}; unsafe extern "C" { - static mut l0_pgtable: [u64; 512]; - static mut l1_pgtable: [u64; 512]; - static mut l2_pgtable: [u64; 512]; - static mut l2k_pgtable: [u64; 512]; - static mut l3_pgtable: [u64; 512]; - static mut L0mib_pgtable: [u64; 512]; - static mut L2mib_pgtable: [u64; 512]; - static mut L4mib_pgtable: [u64; 512]; - static mut L6mib_pgtable: [u64; 512]; - static mut L8mib_pgtable: [u64; 512]; - static mut L10mib_pgtable: [u64; 512]; - static mut L12mib_pgtable: [u64; 512]; - static mut L14mib_pgtable: [u64; 512]; - static mut L16mib_pgtable: [u64; 512]; - static mut L18mib_pgtable: [u64; 512]; + static mut l0_pgtable: [*mut (); 512]; + static mut l1_pgtable: [*mut (); 512]; + static mut l2_pgtable: [*mut (); 512]; + static mut l2k_pgtable: [*mut (); 512]; + static mut l3_pgtable: [*mut (); 512]; + static mut L0mib_pgtable: [*mut (); 512]; + static mut L2mib_pgtable: [*mut (); 512]; + static mut L4mib_pgtable: [*mut (); 512]; + static mut L6mib_pgtable: [*mut (); 512]; + static mut L8mib_pgtable: [*mut (); 512]; + static mut L10mib_pgtable: [*mut (); 512]; + static mut L12mib_pgtable: [*mut (); 512]; + static mut L14mib_pgtable: [*mut (); 512]; + static mut L16mib_pgtable: [*mut (); 512]; + static mut L18mib_pgtable: [*mut (); 512]; } -const PT_PT: u64 = 0x713; -const PT_MEM: u64 = 0x713; -const PT_MEM_CD: u64 = 0x70F; -const PT_SELF: u64 = 1 << 55; +const PT_PT: usize = 0x713; +const PT_MEM: usize = 0x713; +const PT_MEM_CD: usize = 0x70F; +const PT_SELF: usize = 1 << 55; #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { let pgt = unsafe { &mut l0_pgtable }; for i in pgt.iter_mut() { - *i = 0; + *i = ptr::null_mut(); } - pgt[0] = (&raw mut l1_pgtable).expose_provenance() as u64 + PT_PT; - pgt[511] = (&raw mut l0_pgtable).expose_provenance() as u64 + PT_PT + PT_SELF; + pgt[0] = (&raw mut l1_pgtable).wrapping_byte_add(PT_PT).cast(); + pgt[511] = (&raw mut l0_pgtable) + .wrapping_byte_add(PT_PT) + .wrapping_byte_add(PT_SELF) + .cast(); let pgt = unsafe { &mut l1_pgtable }; for i in pgt.iter_mut() { - *i = 0; + *i = ptr::null_mut(); } - pgt[0] = (&raw mut l2_pgtable).expose_provenance() as u64 + PT_PT; - pgt[1] = (&raw mut l2k_pgtable).expose_provenance() as u64 + PT_PT; + pgt[0] = (&raw mut l2_pgtable).wrapping_byte_add(PT_PT).cast(); + pgt[1] = (&raw mut l2k_pgtable).wrapping_byte_add(PT_PT).cast(); let pgt = unsafe { &mut l2_pgtable }; for i in pgt.iter_mut() { - *i = 0; + *i = ptr::null_mut(); } - pgt[0] = (&raw mut l3_pgtable).expose_provenance() as u64 + PT_PT; + pgt[0] = (&raw mut l3_pgtable).wrapping_byte_add(PT_PT).cast(); let pgt = unsafe { &mut l3_pgtable }; for i in pgt.iter_mut() { - *i = 0; + *i = ptr::null_mut(); } - pgt[1] = uart_address as u64 + PT_MEM_CD; + pgt[1] = + ptr::with_exposed_provenance_mut::<()>(uart_address as usize).wrapping_byte_add(PT_MEM_CD); // map kernel to __executable_start and stack below the kernel let pgt = unsafe { &mut l2k_pgtable }; for i in pgt.iter_mut() { - *i = 0; + *i = ptr::null_mut(); } let mib_pgtables = unsafe { @@ -79,12 +83,14 @@ pub unsafe fn init(uart_address: u32) { ] }; - for (mib_i, mib_pgt) in mib_pgtables.into_iter().enumerate() { - pgt[mib_i] = ptr::from_mut(mib_pgt) as u64 + PT_PT; + for (mib_pgt_i, mib_pgt) in mib_pgtables.into_iter().enumerate() { + pgt[mib_pgt_i] = ptr::from_mut(mib_pgt).wrapping_byte_add(PT_PT).cast(); - for (i, entry) in mib_pgt.iter_mut().enumerate() { - let i = mib_i * 512 + i; - *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; + for (entry_i, entry) in mib_pgt.iter_mut().enumerate() { + let total_entry_i = mib_pgt_i * 512 + entry_i; + *entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize) + .wrapping_byte_add(PT_MEM) + .wrapping_byte_add(total_entry_i * BasePageSize::SIZE); } } } From 997e8ef774dac66c4e9855daa596d27a2051f2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 10 Jun 2026 10:14:36 +0200 Subject: [PATCH 09/15] refactor(aarch64): add PageTable type --- src/arch/aarch64/page_tables.rs | 63 +++++++++++++++++---------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index f94d3a27..548f9cba 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -8,21 +8,21 @@ use super::RAM_START; use super::paging::{BasePageSize, PageSize}; unsafe extern "C" { - static mut l0_pgtable: [*mut (); 512]; - static mut l1_pgtable: [*mut (); 512]; - static mut l2_pgtable: [*mut (); 512]; - static mut l2k_pgtable: [*mut (); 512]; - static mut l3_pgtable: [*mut (); 512]; - static mut L0mib_pgtable: [*mut (); 512]; - static mut L2mib_pgtable: [*mut (); 512]; - static mut L4mib_pgtable: [*mut (); 512]; - static mut L6mib_pgtable: [*mut (); 512]; - static mut L8mib_pgtable: [*mut (); 512]; - static mut L10mib_pgtable: [*mut (); 512]; - static mut L12mib_pgtable: [*mut (); 512]; - static mut L14mib_pgtable: [*mut (); 512]; - static mut L16mib_pgtable: [*mut (); 512]; - static mut L18mib_pgtable: [*mut (); 512]; + static mut l0_pgtable: PageTable; + static mut l1_pgtable: PageTable; + static mut l2_pgtable: PageTable; + static mut l2k_pgtable: PageTable; + static mut l3_pgtable: PageTable; + static mut L0mib_pgtable: PageTable; + static mut L2mib_pgtable: PageTable; + static mut L4mib_pgtable: PageTable; + static mut L6mib_pgtable: PageTable; + static mut L8mib_pgtable: PageTable; + static mut L10mib_pgtable: PageTable; + static mut L12mib_pgtable: PageTable; + static mut L14mib_pgtable: PageTable; + static mut L16mib_pgtable: PageTable; + static mut L18mib_pgtable: PageTable; } const PT_PT: usize = 0x713; @@ -32,7 +32,7 @@ const PT_SELF: usize = 1 << 55; #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { - let pgt = unsafe { &mut l0_pgtable }; + let pgt = unsafe { &mut l0_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } @@ -42,20 +42,20 @@ pub unsafe fn init(uart_address: u32) { .wrapping_byte_add(PT_SELF) .cast(); - let pgt = unsafe { &mut l1_pgtable }; + let pgt = unsafe { &mut l1_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } pgt[0] = (&raw mut l2_pgtable).wrapping_byte_add(PT_PT).cast(); pgt[1] = (&raw mut l2k_pgtable).wrapping_byte_add(PT_PT).cast(); - let pgt = unsafe { &mut l2_pgtable }; + let pgt = unsafe { &mut l2_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } pgt[0] = (&raw mut l3_pgtable).wrapping_byte_add(PT_PT).cast(); - let pgt = unsafe { &mut l3_pgtable }; + let pgt = unsafe { &mut l3_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } @@ -63,23 +63,23 @@ pub unsafe fn init(uart_address: u32) { ptr::with_exposed_provenance_mut::<()>(uart_address as usize).wrapping_byte_add(PT_MEM_CD); // map kernel to __executable_start and stack below the kernel - let pgt = unsafe { &mut l2k_pgtable }; + let pgt = unsafe { &mut l2k_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } let mib_pgtables = unsafe { [ - &mut L0mib_pgtable, - &mut L2mib_pgtable, - &mut L4mib_pgtable, - &mut L6mib_pgtable, - &mut L8mib_pgtable, - &mut L10mib_pgtable, - &mut L12mib_pgtable, - &mut L14mib_pgtable, - &mut L16mib_pgtable, - &mut L18mib_pgtable, + &mut L0mib_pgtable.0, + &mut L2mib_pgtable.0, + &mut L4mib_pgtable.0, + &mut L6mib_pgtable.0, + &mut L8mib_pgtable.0, + &mut L10mib_pgtable.0, + &mut L12mib_pgtable.0, + &mut L14mib_pgtable.0, + &mut L16mib_pgtable.0, + &mut L18mib_pgtable.0, ] }; @@ -108,3 +108,6 @@ pub unsafe fn enable() { info!("Successfully set up paging."); } + +#[repr(C, align(0x1000))] +struct PageTable([*mut (); 512]); From 342cfe5cbc983e6b8eea1e18393ad51e9ba1b341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 10 Jun 2026 10:17:36 +0200 Subject: [PATCH 10/15] refactor(aarch64): move page table symbols to Rust --- src/arch/aarch64/entry.s | 50 --------------------------------- src/arch/aarch64/page_tables.rs | 34 +++++++++++----------- 2 files changed, 17 insertions(+), 67 deletions(-) diff --git a/src/arch/aarch64/entry.s b/src/arch/aarch64/entry.s index a7c9f80a..9df42ba3 100644 --- a/src/arch/aarch64/entry.s +++ b/src/arch/aarch64/entry.s @@ -79,53 +79,3 @@ el_1_entry: .size _start, . - _start .type _start, function .global _start - -.section .bss - -.global l0_pgtable -.global l1_pgtable -.global l2_pgtable -.global l2k_pgtable -.global l3_pgtable -.global L0mib_pgtable -.global L2mib_pgtable -.global L4mib_pgtable -.global L6mib_pgtable -.global L8mib_pgtable -.global L10mib_pgtable -.global L12mib_pgtable -.global L14mib_pgtable -.global L16mib_pgtable -.global L18mib_pgtable - -.align 12 -l0_pgtable: - .space 512*8, 0 -l1_pgtable: - .space 512*8, 0 -l2_pgtable: - .space 512*8, 0 -l2k_pgtable: - .space 512*8, 0 -l3_pgtable: - .space 512*8, 0 -L0mib_pgtable: - .space 512*8, 0 -L2mib_pgtable: - .space 512*8, 0 -L4mib_pgtable: - .space 512*8, 0 -L6mib_pgtable: - .space 512*8, 0 -L8mib_pgtable: - .space 512*8, 0 -L10mib_pgtable: - .space 512*8, 0 -L12mib_pgtable: - .space 512*8, 0 -L14mib_pgtable: - .space 512*8, 0 -L16mib_pgtable: - .space 512*8, 0 -L18mib_pgtable: - .space 512*8, 0 diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 548f9cba..64ec6a30 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -1,3 +1,5 @@ +#![allow(non_upper_case_globals)] + use core::ptr; use aarch64_cpu::asm::barrier::{SY, dsb, isb}; @@ -7,23 +9,21 @@ use log::info; use super::RAM_START; use super::paging::{BasePageSize, PageSize}; -unsafe extern "C" { - static mut l0_pgtable: PageTable; - static mut l1_pgtable: PageTable; - static mut l2_pgtable: PageTable; - static mut l2k_pgtable: PageTable; - static mut l3_pgtable: PageTable; - static mut L0mib_pgtable: PageTable; - static mut L2mib_pgtable: PageTable; - static mut L4mib_pgtable: PageTable; - static mut L6mib_pgtable: PageTable; - static mut L8mib_pgtable: PageTable; - static mut L10mib_pgtable: PageTable; - static mut L12mib_pgtable: PageTable; - static mut L14mib_pgtable: PageTable; - static mut L16mib_pgtable: PageTable; - static mut L18mib_pgtable: PageTable; -} +static mut l0_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut l1_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut l2_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut l2k_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut l3_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L0mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L2mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L4mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L6mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L8mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L10mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L12mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L14mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L16mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut L18mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); const PT_PT: usize = 0x713; const PT_MEM: usize = 0x713; From 6046e7edc3185ee6d26fce032ecf6be91c032ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 10 Jun 2026 11:40:08 +0200 Subject: [PATCH 11/15] refactor(aarch64): extract and document descriptor values --- src/arch/aarch64/page_tables.rs | 71 ++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 64ec6a30..d91e084c 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -25,42 +25,45 @@ static mut L14mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); static mut L16mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); static mut L18mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -const PT_PT: usize = 0x713; -const PT_MEM: usize = 0x713; -const PT_MEM_CD: usize = 0x70F; -const PT_SELF: usize = 1 << 55; - #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { let pgt = unsafe { &mut l0_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l1_pgtable).wrapping_byte_add(PT_PT).cast(); + pgt[0] = (&raw mut l1_pgtable) + .wrapping_byte_add(descr::NORMAL) + .cast(); pgt[511] = (&raw mut l0_pgtable) - .wrapping_byte_add(PT_PT) - .wrapping_byte_add(PT_SELF) + .wrapping_byte_add(descr::NORMAL) + .wrapping_byte_add(descr::SELF) .cast(); let pgt = unsafe { &mut l1_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l2_pgtable).wrapping_byte_add(PT_PT).cast(); - pgt[1] = (&raw mut l2k_pgtable).wrapping_byte_add(PT_PT).cast(); + pgt[0] = (&raw mut l2_pgtable) + .wrapping_byte_add(descr::NORMAL) + .cast(); + pgt[1] = (&raw mut l2k_pgtable) + .wrapping_byte_add(descr::NORMAL) + .cast(); let pgt = unsafe { &mut l2_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l3_pgtable).wrapping_byte_add(PT_PT).cast(); + pgt[0] = (&raw mut l3_pgtable) + .wrapping_byte_add(descr::NORMAL) + .cast(); let pgt = unsafe { &mut l3_pgtable.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[1] = - ptr::with_exposed_provenance_mut::<()>(uart_address as usize).wrapping_byte_add(PT_MEM_CD); + pgt[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize) + .wrapping_byte_add(descr::NON_CACHEABLE); // map kernel to __executable_start and stack below the kernel let pgt = unsafe { &mut l2k_pgtable.0 }; @@ -84,12 +87,14 @@ pub unsafe fn init(uart_address: u32) { }; for (mib_pgt_i, mib_pgt) in mib_pgtables.into_iter().enumerate() { - pgt[mib_pgt_i] = ptr::from_mut(mib_pgt).wrapping_byte_add(PT_PT).cast(); + pgt[mib_pgt_i] = ptr::from_mut(mib_pgt) + .wrapping_byte_add(descr::NORMAL) + .cast(); for (entry_i, entry) in mib_pgt.iter_mut().enumerate() { let total_entry_i = mib_pgt_i * 512 + entry_i; *entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize) - .wrapping_byte_add(PT_MEM) + .wrapping_byte_add(descr::NORMAL) .wrapping_byte_add(total_entry_i * BasePageSize::SIZE); } } @@ -111,3 +116,39 @@ pub unsafe fn enable() { #[repr(C, align(0x1000))] struct PageTable([*mut (); 512]); + +/// Descriptor values +/// +/// For reference, see . +mod descr { + pub const NORMAL: usize = AF | SH_INNER | attr_indx(4) | TABLE | VALID; + pub const NON_CACHEABLE: usize = AF | SH_INNER | attr_indx(3) | TABLE | VALID; + + /// Valid descriptor + const VALID: usize = 1; + + /// Table descriptor + const TABLE: usize = 1 << 1; + + /// Attribute index + /// + /// Selects the corresponding `MAIR` memory region attributes. + const fn attr_indx(indx: u8) -> usize { + assert!(indx < 1 << 5); + (indx as usize) << 2 + } + + /// Shareability + /// + /// Inner Shareable + const SH_INNER: usize = 1 << 8 | 1 << 9; + + /// Access flag + const AF: usize = 1 << 10; + + /// A software-defined marker for marking a self-referential entry. + /// + /// This can be used for recursive page tables by the kernel, but is currently not needed. + // FIXME: remove once the kernel set's up it's own page tables. + pub const SELF: usize = 1 << 55; +} From bb1dc3e4f98d1c5fb8c2fffc9296047704744cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 11 Jun 2026 11:38:04 +0200 Subject: [PATCH 12/15] refactor(aarch64): rename page tables --- src/arch/aarch64/page_tables.rs | 74 ++++++++++++++++----------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index d91e084c..b2449ae8 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -1,5 +1,3 @@ -#![allow(non_upper_case_globals)] - use core::ptr; use aarch64_cpu::asm::barrier::{SY, dsb, isb}; @@ -9,56 +7,56 @@ use log::info; use super::RAM_START; use super::paging::{BasePageSize, PageSize}; -static mut l0_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut l1_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut l2_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut l2k_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut l3_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L0mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L2mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L4mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L6mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L8mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L10mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L12mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L14mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L16mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); -static mut L18mib_pgtable: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_0_TABLE: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_1_TABLE: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_2_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_2_TABLE_RAM: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_1: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_2: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_3: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_4: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_5: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_6: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_7: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_8: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_9: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLE_RAM_10: PageTable = PageTable([ptr::null_mut(); _]); #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { - let pgt = unsafe { &mut l0_pgtable.0 }; + let pgt = unsafe { &mut LEVEL_0_TABLE.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l1_pgtable) + pgt[0] = (&raw mut LEVEL_1_TABLE) .wrapping_byte_add(descr::NORMAL) .cast(); - pgt[511] = (&raw mut l0_pgtable) + pgt[511] = (&raw mut LEVEL_0_TABLE) .wrapping_byte_add(descr::NORMAL) .wrapping_byte_add(descr::SELF) .cast(); - let pgt = unsafe { &mut l1_pgtable.0 }; + let pgt = unsafe { &mut LEVEL_1_TABLE.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l2_pgtable) + pgt[0] = (&raw mut LEVEL_2_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - pgt[1] = (&raw mut l2k_pgtable) + pgt[1] = (&raw mut LEVEL_2_TABLE_RAM) .wrapping_byte_add(descr::NORMAL) .cast(); - let pgt = unsafe { &mut l2_pgtable.0 }; + let pgt = unsafe { &mut LEVEL_2_TABLE_SERIAL.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } - pgt[0] = (&raw mut l3_pgtable) + pgt[0] = (&raw mut LEVEL_3_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - let pgt = unsafe { &mut l3_pgtable.0 }; + let pgt = unsafe { &mut LEVEL_3_TABLE_SERIAL.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } @@ -66,23 +64,23 @@ pub unsafe fn init(uart_address: u32) { .wrapping_byte_add(descr::NON_CACHEABLE); // map kernel to __executable_start and stack below the kernel - let pgt = unsafe { &mut l2k_pgtable.0 }; + let pgt = unsafe { &mut LEVEL_2_TABLE_RAM.0 }; for i in pgt.iter_mut() { *i = ptr::null_mut(); } let mib_pgtables = unsafe { [ - &mut L0mib_pgtable.0, - &mut L2mib_pgtable.0, - &mut L4mib_pgtable.0, - &mut L6mib_pgtable.0, - &mut L8mib_pgtable.0, - &mut L10mib_pgtable.0, - &mut L12mib_pgtable.0, - &mut L14mib_pgtable.0, - &mut L16mib_pgtable.0, - &mut L18mib_pgtable.0, + &mut LEVEL_3_TABLE_RAM_1.0, + &mut LEVEL_3_TABLE_RAM_2.0, + &mut LEVEL_3_TABLE_RAM_3.0, + &mut LEVEL_3_TABLE_RAM_4.0, + &mut LEVEL_3_TABLE_RAM_5.0, + &mut LEVEL_3_TABLE_RAM_6.0, + &mut LEVEL_3_TABLE_RAM_7.0, + &mut LEVEL_3_TABLE_RAM_8.0, + &mut LEVEL_3_TABLE_RAM_9.0, + &mut LEVEL_3_TABLE_RAM_10.0, ] }; @@ -103,7 +101,7 @@ pub unsafe fn init(uart_address: u32) { pub unsafe fn enable() { // Set Translation Table Base Registers (TTBR) TTBR1_EL1.set(0); - TTBR0_EL1.set((&raw mut l0_pgtable).expose_provenance() as u64); + TTBR0_EL1.set((&raw mut LEVEL_0_TABLE).expose_provenance() as u64); dsb(SY); isb(SY); From f57f0f5729f214c498a852a5ebf2f58cc9123af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 11 Jun 2026 11:39:13 +0200 Subject: [PATCH 13/15] fix(aarch64): don't zero the page tables at runtime --- src/arch/aarch64/page_tables.rs | 52 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index b2449ae8..5f6f4b1f 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -25,51 +25,35 @@ static mut LEVEL_3_TABLE_RAM_10: PageTable = PageTable([ptr::null_mut(); _]); #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { - let pgt = unsafe { &mut LEVEL_0_TABLE.0 }; - for i in pgt.iter_mut() { - *i = ptr::null_mut(); - } - pgt[0] = (&raw mut LEVEL_1_TABLE) + let level_0_table = unsafe { &mut LEVEL_0_TABLE.0 }; + level_0_table[0] = (&raw mut LEVEL_1_TABLE) .wrapping_byte_add(descr::NORMAL) .cast(); - pgt[511] = (&raw mut LEVEL_0_TABLE) + level_0_table[511] = (&raw mut LEVEL_0_TABLE) .wrapping_byte_add(descr::NORMAL) .wrapping_byte_add(descr::SELF) .cast(); - let pgt = unsafe { &mut LEVEL_1_TABLE.0 }; - for i in pgt.iter_mut() { - *i = ptr::null_mut(); - } - pgt[0] = (&raw mut LEVEL_2_TABLE_SERIAL) + let level_1_table = unsafe { &mut LEVEL_1_TABLE.0 }; + level_1_table[0] = (&raw mut LEVEL_2_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - pgt[1] = (&raw mut LEVEL_2_TABLE_RAM) + level_1_table[1] = (&raw mut LEVEL_2_TABLE_RAM) .wrapping_byte_add(descr::NORMAL) .cast(); - let pgt = unsafe { &mut LEVEL_2_TABLE_SERIAL.0 }; - for i in pgt.iter_mut() { - *i = ptr::null_mut(); - } - pgt[0] = (&raw mut LEVEL_3_TABLE_SERIAL) + let level_2_table_serial = unsafe { &mut LEVEL_2_TABLE_SERIAL.0 }; + level_2_table_serial[0] = (&raw mut LEVEL_3_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - let pgt = unsafe { &mut LEVEL_3_TABLE_SERIAL.0 }; - for i in pgt.iter_mut() { - *i = ptr::null_mut(); - } - pgt[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize) + let level_3_table_serial = unsafe { &mut LEVEL_3_TABLE_SERIAL.0 }; + level_3_table_serial[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize) .wrapping_byte_add(descr::NON_CACHEABLE); - // map kernel to __executable_start and stack below the kernel - let pgt = unsafe { &mut LEVEL_2_TABLE_RAM.0 }; - for i in pgt.iter_mut() { - *i = ptr::null_mut(); - } + let level_2_table_ram = unsafe { &mut LEVEL_2_TABLE_RAM.0 }; - let mib_pgtables = unsafe { + let level_3_tables_ram = unsafe { [ &mut LEVEL_3_TABLE_RAM_1.0, &mut LEVEL_3_TABLE_RAM_2.0, @@ -84,16 +68,16 @@ pub unsafe fn init(uart_address: u32) { ] }; - for (mib_pgt_i, mib_pgt) in mib_pgtables.into_iter().enumerate() { - pgt[mib_pgt_i] = ptr::from_mut(mib_pgt) + for (i, level_3_table_ram) in level_3_tables_ram.into_iter().enumerate() { + level_2_table_ram[i] = ptr::from_mut(level_3_table_ram) .wrapping_byte_add(descr::NORMAL) .cast(); - for (entry_i, entry) in mib_pgt.iter_mut().enumerate() { - let total_entry_i = mib_pgt_i * 512 + entry_i; + for (entry_i, entry) in level_3_table_ram.iter_mut().enumerate() { + let addr = (i * 512 + entry_i) * BasePageSize::SIZE; *entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize) - .wrapping_byte_add(descr::NORMAL) - .wrapping_byte_add(total_entry_i * BasePageSize::SIZE); + .wrapping_byte_add(addr) + .wrapping_byte_add(descr::NORMAL); } } } From 589fcd9aa94b37f366e52c7b6c3afd0f0b6b43f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 11 Jun 2026 11:45:15 +0200 Subject: [PATCH 14/15] refactor(aarch64): combine level 3 tables for RAM --- src/arch/aarch64/page_tables.rs | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 5f6f4b1f..84069ed7 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -12,16 +12,7 @@ static mut LEVEL_1_TABLE: PageTable = PageTable([ptr::null_mut(); _]); static mut LEVEL_2_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); static mut LEVEL_2_TABLE_RAM: PageTable = PageTable([ptr::null_mut(); _]); static mut LEVEL_3_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_1: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_2: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_3: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_4: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_5: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_6: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_7: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_8: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_9: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_RAM_10: PageTable = PageTable([ptr::null_mut(); _]); +static mut LEVEL_3_TABLES_RAM: [PageTable; 10] = [PageTable([ptr::null_mut(); _]); 10]; #[allow(static_mut_refs)] // FIXME: disallow pub unsafe fn init(uart_address: u32) { @@ -53,27 +44,12 @@ pub unsafe fn init(uart_address: u32) { let level_2_table_ram = unsafe { &mut LEVEL_2_TABLE_RAM.0 }; - let level_3_tables_ram = unsafe { - [ - &mut LEVEL_3_TABLE_RAM_1.0, - &mut LEVEL_3_TABLE_RAM_2.0, - &mut LEVEL_3_TABLE_RAM_3.0, - &mut LEVEL_3_TABLE_RAM_4.0, - &mut LEVEL_3_TABLE_RAM_5.0, - &mut LEVEL_3_TABLE_RAM_6.0, - &mut LEVEL_3_TABLE_RAM_7.0, - &mut LEVEL_3_TABLE_RAM_8.0, - &mut LEVEL_3_TABLE_RAM_9.0, - &mut LEVEL_3_TABLE_RAM_10.0, - ] - }; - - for (i, level_3_table_ram) in level_3_tables_ram.into_iter().enumerate() { + for (i, level_3_table_ram) in unsafe { LEVEL_3_TABLES_RAM.iter_mut().enumerate() } { level_2_table_ram[i] = ptr::from_mut(level_3_table_ram) .wrapping_byte_add(descr::NORMAL) .cast(); - for (entry_i, entry) in level_3_table_ram.iter_mut().enumerate() { + for (entry_i, entry) in level_3_table_ram.0.iter_mut().enumerate() { let addr = (i * 512 + entry_i) * BasePageSize::SIZE; *entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize) .wrapping_byte_add(addr) @@ -96,6 +72,7 @@ pub unsafe fn enable() { info!("Successfully set up paging."); } +#[derive(Clone, Copy, Debug)] #[repr(C, align(0x1000))] struct PageTable([*mut (); 512]); From 5743bb2a9cf375ebc2c176508d71b635b31f7104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Thu, 11 Jun 2026 12:19:44 +0200 Subject: [PATCH 15/15] refactor(aarch64): build page tables at build time --- src/arch/aarch64/page_tables.rs | 88 +++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/src/arch/aarch64/page_tables.rs b/src/arch/aarch64/page_tables.rs index 84069ed7..e18ee115 100644 --- a/src/arch/aarch64/page_tables.rs +++ b/src/arch/aarch64/page_tables.rs @@ -7,54 +7,90 @@ use log::info; use super::RAM_START; use super::paging::{BasePageSize, PageSize}; -static mut LEVEL_0_TABLE: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_1_TABLE: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_2_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_2_TABLE_RAM: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); -static mut LEVEL_3_TABLES_RAM: [PageTable; 10] = [PageTable([ptr::null_mut(); _]); 10]; +static mut LEVEL_0_TABLE: PageTable = { + let mut table = [ptr::null_mut(); _]; -#[allow(static_mut_refs)] // FIXME: disallow -pub unsafe fn init(uart_address: u32) { - let level_0_table = unsafe { &mut LEVEL_0_TABLE.0 }; - level_0_table[0] = (&raw mut LEVEL_1_TABLE) + table[0] = (&raw mut LEVEL_1_TABLE) .wrapping_byte_add(descr::NORMAL) .cast(); - level_0_table[511] = (&raw mut LEVEL_0_TABLE) + table[511] = (&raw mut LEVEL_0_TABLE) .wrapping_byte_add(descr::NORMAL) .wrapping_byte_add(descr::SELF) .cast(); - let level_1_table = unsafe { &mut LEVEL_1_TABLE.0 }; - level_1_table[0] = (&raw mut LEVEL_2_TABLE_SERIAL) + PageTable(table) +}; + +static mut LEVEL_1_TABLE: PageTable = { + let mut table = [ptr::null_mut(); _]; + + table[0] = (&raw mut LEVEL_2_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - level_1_table[1] = (&raw mut LEVEL_2_TABLE_RAM) + table[1] = (&raw mut LEVEL_2_TABLE_RAM) .wrapping_byte_add(descr::NORMAL) .cast(); - let level_2_table_serial = unsafe { &mut LEVEL_2_TABLE_SERIAL.0 }; - level_2_table_serial[0] = (&raw mut LEVEL_3_TABLE_SERIAL) + PageTable(table) +}; + +static mut LEVEL_2_TABLE_SERIAL: PageTable = { + let mut table = [ptr::null_mut(); _]; + + table[0] = (&raw mut LEVEL_3_TABLE_SERIAL) .wrapping_byte_add(descr::NORMAL) .cast(); - let level_3_table_serial = unsafe { &mut LEVEL_3_TABLE_SERIAL.0 }; - level_3_table_serial[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize) - .wrapping_byte_add(descr::NON_CACHEABLE); + PageTable(table) +}; - let level_2_table_ram = unsafe { &mut LEVEL_2_TABLE_RAM.0 }; +static mut LEVEL_2_TABLE_RAM: PageTable = { + let mut table = [ptr::null_mut(); _]; - for (i, level_3_table_ram) in unsafe { LEVEL_3_TABLES_RAM.iter_mut().enumerate() } { - level_2_table_ram[i] = ptr::from_mut(level_3_table_ram) - .wrapping_byte_add(descr::NORMAL) - .cast(); + let mut entry_i = 0; + while entry_i < 10usize { + let entry = &mut table[entry_i]; - for (entry_i, entry) in level_3_table_ram.0.iter_mut().enumerate() { - let addr = (i * 512 + entry_i) * BasePageSize::SIZE; + let level_3_table = unsafe { &raw mut LEVEL_3_TABLES_RAM[entry_i] }; + *entry = level_3_table.wrapping_byte_add(descr::NORMAL).cast(); + + entry_i += 1; + } + + PageTable(table) +}; + +static mut LEVEL_3_TABLE_SERIAL: PageTable = PageTable([ptr::null_mut(); _]); + +static mut LEVEL_3_TABLES_RAM: [PageTable; 10] = { + let mut tables = [PageTable([ptr::null_mut(); _]); _]; + + let mut table_i = 0; + while table_i < tables.len() { + let table = &mut tables[table_i].0; + + let mut entry_i = 0; + while entry_i < table.len() { + let entry = &mut table[entry_i]; + + let addr = (table_i * 512 + entry_i) * BasePageSize::SIZE; *entry = ptr::with_exposed_provenance_mut::<()>(RAM_START as usize) .wrapping_byte_add(addr) .wrapping_byte_add(descr::NORMAL); + + entry_i += 1; } + + table_i += 1; + } + + tables +}; + +pub unsafe fn init(uart_address: u32) { + unsafe { + LEVEL_3_TABLE_SERIAL.0[1] = ptr::with_exposed_provenance_mut::<()>(uart_address as usize) + .wrapping_byte_add(descr::NON_CACHEABLE); } }