diff --git a/10_virtual_mem_part1_identity_mapping/README.md b/10_virtual_mem_part1_identity_mapping/README.md index 04b82eca..8bfd54fa 100644 --- a/10_virtual_mem_part1_identity_mapping/README.md +++ b/10_virtual_mem_part1_identity_mapping/README.md @@ -331,7 +331,7 @@ Minipush 1.0 [ 0.811829] MMU online. Special regions: [ 0.812306] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data [ 0.813324] 0x1fff0000 - 0x1fffffff | 64 KiB | Dev RW PXN | Remapped Device MMIO -[ 0.814310] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO +[ 0.814310] 0x3f000000 - 0x4000ffff | 17 MiB | Dev RW PXN | Device MMIO [ 0.815198] Current privilege level: EL1 [ 0.815675] Exception handling state: [ 0.816119] Debug: Masked @@ -1079,10 +1079,37 @@ diff -uNr 09_privilege_level/src/bsp.rs 10_virtual_mem_part1_identity_mapping/sr #[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] mod raspberrypi; +diff -uNr 09_privilege_level/src/common.rs 10_virtual_mem_part1_identity_mapping/src/common.rs +--- 09_privilege_level/src/common.rs ++++ 10_virtual_mem_part1_identity_mapping/src/common.rs +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: MIT OR Apache-2.0 ++// ++// Copyright (c) 2020-2022 Andre Richter ++ ++//! General purpose code. ++ ++/// Convert a size into human readable format. ++pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { ++ const KIB: usize = 1024; ++ const MIB: usize = 1024 * 1024; ++ const GIB: usize = 1024 * 1024 * 1024; ++ ++ if (size / GIB) > 0 { ++ (size.div_ceil(GIB), "GiB") ++ } else if (size / MIB) > 0 { ++ (size.div_ceil(MIB), "MiB") ++ } else if (size / KIB) > 0 { ++ (size.div_ceil(KIB), "KiB") ++ } else { ++ (size, "Byte") ++ } ++} + diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/src/main.rs --- 09_privilege_level/src/main.rs +++ 10_virtual_mem_part1_identity_mapping/src/main.rs -@@ -107,7 +107,9 @@ +@@ -107,18 +107,23 @@ //! 2. Once finished with architectural setup, the arch code calls `kernel_init()`. #![allow(clippy::upper_case_acronyms)] @@ -1090,9 +1117,15 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s #![feature(asm_const)] +#![feature(core_intrinsics)] #![feature(format_args_nl)] ++#![feature(int_roundings)] #![feature(panic_info_message)] #![feature(trait_alias)] -@@ -119,6 +121,7 @@ + #![no_main] + #![no_std] + + mod bsp; ++mod common; + mod console; mod cpu; mod driver; mod exception; @@ -1100,7 +1133,7 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s mod panic_wait; mod print; mod synchronization; -@@ -129,9 +132,17 @@ +@@ -129,9 +134,17 @@ /// # Safety /// /// - Only a single core must be active and running this function. @@ -1119,7 +1152,7 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s for i in bsp::driver::driver_manager().all_device_drivers().iter() { if let Err(x) = i.init() { -@@ -147,7 +158,7 @@ +@@ -147,7 +160,7 @@ /// The main function running after the early init. fn kernel_main() -> ! { @@ -1128,7 +1161,7 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s use core::time::Duration; use driver::interface::DriverManager; use time::interface::TimeManager; -@@ -159,6 +170,9 @@ +@@ -159,6 +172,9 @@ ); info!("Booting on: {}", bsp::board_name()); @@ -1138,7 +1171,7 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s let (_, privilege_level) = exception::current_privilege_level(); info!("Current privilege level: {}", privilege_level); -@@ -182,6 +196,13 @@ +@@ -182,6 +198,13 @@ info!("Timer test, spinning for 1 second"); time::time_manager().spin_for(Duration::from_secs(1)); @@ -1175,7 +1208,7 @@ diff -uNr 09_privilege_level/src/memory/mmu/translation_table.rs 10_virtual_mem_ diff -uNr 09_privilege_level/src/memory/mmu.rs 10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs --- 09_privilege_level/src/memory/mmu.rs +++ 10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs -@@ -0,0 +1,264 @@ +@@ -0,0 +1,253 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter @@ -1198,6 +1231,7 @@ diff -uNr 09_privilege_level/src/memory/mmu.rs 10_virtual_mem_part1_identity_map + +mod translation_table; + ++use crate::common; +use core::{fmt, ops::RangeInclusive}; + +//-------------------------------------------------------------------------------------------------- @@ -1357,19 +1391,7 @@ diff -uNr 09_privilege_level/src/memory/mmu.rs 10_virtual_mem_part1_identity_map + let end = *(self.virtual_range)().end(); + let size = end - start + 1; + -+ // log2(1024). -+ const KIB_RSHIFT: u32 = 10; -+ -+ // log2(1024 * 1024). -+ const MIB_RSHIFT: u32 = 20; -+ -+ let (size, unit) = if (size >> MIB_RSHIFT) > 0 { -+ (size >> MIB_RSHIFT, "MiB") -+ } else if (size >> KIB_RSHIFT) > 0 { -+ (size >> KIB_RSHIFT, "KiB") -+ } else { -+ (size, "Byte") -+ }; ++ let (size, unit) = common::size_human_readable_ceil(size); + + let attr = match self.attribute_fields.mem_attributes { + MemAttributes::CacheableDRAM => "C", diff --git a/10_virtual_mem_part1_identity_mapping/src/common.rs b/10_virtual_mem_part1_identity_mapping/src/common.rs new file mode 100644 index 00000000..27679aea --- /dev/null +++ b/10_virtual_mem_part1_identity_mapping/src/common.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter + +//! General purpose code. + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/10_virtual_mem_part1_identity_mapping/src/main.rs b/10_virtual_mem_part1_identity_mapping/src/main.rs index 6f92c676..40b6d13b 100644 --- a/10_virtual_mem_part1_identity_mapping/src/main.rs +++ b/10_virtual_mem_part1_identity_mapping/src/main.rs @@ -111,12 +111,14 @@ #![feature(asm_const)] #![feature(core_intrinsics)] #![feature(format_args_nl)] +#![feature(int_roundings)] #![feature(panic_info_message)] #![feature(trait_alias)] #![no_main] #![no_std] mod bsp; +mod common; mod console; mod cpu; mod driver; diff --git a/10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs b/10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs index 17a98274..bef4c1d1 100644 --- a/10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs +++ b/10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs @@ -20,6 +20,7 @@ mod arch_mmu; mod translation_table; +use crate::common; use core::{fmt, ops::RangeInclusive}; //-------------------------------------------------------------------------------------------------- @@ -179,19 +180,7 @@ impl fmt::Display for TranslationDescriptor { let end = *(self.virtual_range)().end(); let size = end - start + 1; - // log2(1024). - const KIB_RSHIFT: u32 = 10; - - // log2(1024 * 1024). - const MIB_RSHIFT: u32 = 20; - - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match self.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", diff --git a/11_exceptions_part1_groundwork/README.md b/11_exceptions_part1_groundwork/README.md index 355ea297..d0b4b7f7 100644 --- a/11_exceptions_part1_groundwork/README.md +++ b/11_exceptions_part1_groundwork/README.md @@ -421,7 +421,7 @@ Minipush 1.0 [ 0.798530] Booting on: Raspberry Pi 3 [ 0.798985] MMU online. Special regions: [ 0.799462] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data -[ 0.800480] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO +[ 0.800480] 0x3f000000 - 0x4000ffff | 17 MiB | Dev RW PXN | Device MMIO [ 0.801369] Current privilege level: EL1 [ 0.801845] Exception handling state: [ 0.802290] Debug: Masked @@ -1024,7 +1024,7 @@ diff -uNr 10_virtual_mem_part1_identity_mapping/src/exception.rs 11_exceptions_p diff -uNr 10_virtual_mem_part1_identity_mapping/src/main.rs 11_exceptions_part1_groundwork/src/main.rs --- 10_virtual_mem_part1_identity_mapping/src/main.rs +++ 11_exceptions_part1_groundwork/src/main.rs -@@ -140,6 +140,8 @@ +@@ -142,6 +142,8 @@ use driver::interface::DriverManager; use memory::mmu::interface::MMU; @@ -1033,7 +1033,7 @@ diff -uNr 10_virtual_mem_part1_identity_mapping/src/main.rs 11_exceptions_part1_ if let Err(string) = memory::mmu::mmu().enable_mmu_and_caching() { panic!("MMU: {}", string); } -@@ -158,7 +160,7 @@ +@@ -160,7 +162,7 @@ /// The main function running after the early init. fn kernel_main() -> ! { @@ -1042,7 +1042,7 @@ diff -uNr 10_virtual_mem_part1_identity_mapping/src/main.rs 11_exceptions_part1_ use core::time::Duration; use driver::interface::DriverManager; use time::interface::TimeManager; -@@ -196,13 +198,28 @@ +@@ -198,13 +200,28 @@ info!("Timer test, spinning for 1 second"); time::time_manager().spin_for(Duration::from_secs(1)); diff --git a/11_exceptions_part1_groundwork/src/common.rs b/11_exceptions_part1_groundwork/src/common.rs new file mode 100644 index 00000000..27679aea --- /dev/null +++ b/11_exceptions_part1_groundwork/src/common.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter + +//! General purpose code. + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/11_exceptions_part1_groundwork/src/main.rs b/11_exceptions_part1_groundwork/src/main.rs index 12386153..585382a5 100644 --- a/11_exceptions_part1_groundwork/src/main.rs +++ b/11_exceptions_part1_groundwork/src/main.rs @@ -111,12 +111,14 @@ #![feature(asm_const)] #![feature(core_intrinsics)] #![feature(format_args_nl)] +#![feature(int_roundings)] #![feature(panic_info_message)] #![feature(trait_alias)] #![no_main] #![no_std] mod bsp; +mod common; mod console; mod cpu; mod driver; diff --git a/11_exceptions_part1_groundwork/src/memory/mmu.rs b/11_exceptions_part1_groundwork/src/memory/mmu.rs index 17a98274..bef4c1d1 100644 --- a/11_exceptions_part1_groundwork/src/memory/mmu.rs +++ b/11_exceptions_part1_groundwork/src/memory/mmu.rs @@ -20,6 +20,7 @@ mod arch_mmu; mod translation_table; +use crate::common; use core::{fmt, ops::RangeInclusive}; //-------------------------------------------------------------------------------------------------- @@ -179,19 +180,7 @@ impl fmt::Display for TranslationDescriptor { let end = *(self.virtual_range)().end(); let size = end - start + 1; - // log2(1024). - const KIB_RSHIFT: u32 = 10; - - // log2(1024 * 1024). - const MIB_RSHIFT: u32 = 20; - - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match self.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", diff --git a/12_integrated_testing/kernel/src/common.rs b/12_integrated_testing/kernel/src/common.rs new file mode 100644 index 00000000..27679aea --- /dev/null +++ b/12_integrated_testing/kernel/src/common.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter + +//! General purpose code. + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/12_integrated_testing/kernel/src/lib.rs b/12_integrated_testing/kernel/src/lib.rs index eef112f0..4a41bbfe 100644 --- a/12_integrated_testing/kernel/src/lib.rs +++ b/12_integrated_testing/kernel/src/lib.rs @@ -113,6 +113,7 @@ #![feature(asm_const)] #![feature(core_intrinsics)] #![feature(format_args_nl)] +#![feature(int_roundings)] #![feature(linkage)] #![feature(panic_info_message)] #![feature(trait_alias)] @@ -127,6 +128,7 @@ mod panic_wait; mod synchronization; pub mod bsp; +pub mod common; pub mod console; pub mod cpu; pub mod driver; diff --git a/12_integrated_testing/kernel/src/memory/mmu.rs b/12_integrated_testing/kernel/src/memory/mmu.rs index a68973e7..b313d7d4 100644 --- a/12_integrated_testing/kernel/src/memory/mmu.rs +++ b/12_integrated_testing/kernel/src/memory/mmu.rs @@ -20,6 +20,7 @@ mod arch_mmu; mod translation_table; +use crate::common; use core::{fmt, ops::RangeInclusive}; //-------------------------------------------------------------------------------------------------- @@ -178,19 +179,7 @@ impl fmt::Display for TranslationDescriptor { let end = *(self.virtual_range)().end(); let size = end - start + 1; - // log2(1024). - const KIB_RSHIFT: u32 = 10; - - // log2(1024 * 1024). - const MIB_RSHIFT: u32 = 20; - - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match self.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", diff --git a/13_exceptions_part2_peripheral_IRQs/README.md b/13_exceptions_part2_peripheral_IRQs/README.md index bc468be8..e2e2e169 100644 --- a/13_exceptions_part2_peripheral_IRQs/README.md +++ b/13_exceptions_part2_peripheral_IRQs/README.md @@ -682,7 +682,7 @@ Minipush 1.0 [ 0.822700] Booting on: Raspberry Pi 3 [ 0.823155] MMU online. Special regions: [ 0.823632] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data -[ 0.824650] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO +[ 0.824650] 0x3f000000 - 0x4000ffff | 17 MiB | Dev RW PXN | Device MMIO [ 0.825539] Current privilege level: EL1 [ 0.826015] Exception handling state: [ 0.826459] Debug: Masked @@ -726,7 +726,7 @@ Minipush 1.0 [ 0.886886] Booting on: Raspberry Pi 4 [ 0.887341] MMU online. Special regions: [ 0.887818] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data -[ 0.888836] 0xfe000000 - 0xff84ffff | 24 MiB | Dev RW PXN | Device MMIO +[ 0.888836] 0xfe000000 - 0xff84ffff | 25 MiB | Dev RW PXN | Device MMIO [ 0.889725] Current privilege level: EL1 [ 0.890201] Exception handling state: [ 0.890645] Debug: Masked @@ -2407,7 +2407,7 @@ diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptio diff -uNr 12_integrated_testing/kernel/src/lib.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs --- 12_integrated_testing/kernel/src/lib.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs -@@ -133,6 +133,7 @@ +@@ -135,6 +135,7 @@ pub mod exception; pub mod memory; pub mod print; diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs new file mode 100644 index 00000000..27679aea --- /dev/null +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter + +//! General purpose code. + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs index c4b07809..6c5bc6b3 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs @@ -113,6 +113,7 @@ #![feature(asm_const)] #![feature(core_intrinsics)] #![feature(format_args_nl)] +#![feature(int_roundings)] #![feature(linkage)] #![feature(panic_info_message)] #![feature(trait_alias)] @@ -127,6 +128,7 @@ mod panic_wait; mod synchronization; pub mod bsp; +pub mod common; pub mod console; pub mod cpu; pub mod driver; diff --git a/13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs b/13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs index a68973e7..b313d7d4 100644 --- a/13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs +++ b/13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs @@ -20,6 +20,7 @@ mod arch_mmu; mod translation_table; +use crate::common; use core::{fmt, ops::RangeInclusive}; //-------------------------------------------------------------------------------------------------- @@ -178,19 +179,7 @@ impl fmt::Display for TranslationDescriptor { let end = *(self.virtual_range)().end(); let size = end - start + 1; - // log2(1024). - const KIB_RSHIFT: u32 = 10; - - // log2(1024 * 1024). - const MIB_RSHIFT: u32 = 20; - - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match self.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", diff --git a/14_virtual_mem_part2_mmio_remap/README.md b/14_virtual_mem_part2_mmio_remap/README.md index b5caac52..be0997ac 100644 --- a/14_virtual_mem_part2_mmio_remap/README.md +++ b/14_virtual_mem_part2_mmio_remap/README.md @@ -2053,13 +2053,10 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi.rs 14_v diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs 14_virtual_mem_part2_mmio_remap/kernel/src/common.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/common.rs -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: MIT OR Apache-2.0 -+// -+// Copyright (c) 2020-2022 Andre Richter -+ -+//! General purpose code. -+ +@@ -4,6 +4,30 @@ + + //! General purpose code. + +/// Check if a value is aligned to a given size. +#[inline(always)] +pub const fn is_aligned(value: usize, alignment: usize) -> bool { @@ -2083,6 +2080,10 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs 14_virtual_me + + (value + alignment - 1) & !(alignment - 1) +} ++ + /// Convert a size into human readable format. + pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/console/null_console.rs 14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/console/null_console.rs @@ -2110,7 +2111,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/console/null_console.rs +pub static NULL_CONSOLE: NullConsole = NullConsole {}; + +//-------------------------------------------------------------------------------------------------- -+// Private Code ++// Public Code +//-------------------------------------------------------------------------------------------------- + +impl interface::Write for NullConsole { @@ -2323,11 +2324,12 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous. diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs -@@ -113,8 +113,11 @@ +@@ -113,9 +113,12 @@ #![feature(asm_const)] #![feature(core_intrinsics)] #![feature(format_args_nl)] +#![feature(generic_const_exprs)] + #![feature(int_roundings)] +#![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -2335,15 +2337,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs 14_virtual_mem_p #![feature(trait_alias)] #![no_std] // Testing -@@ -127,6 +130,7 @@ - mod synchronization; - - pub mod bsp; -+pub mod common; - pub mod console; - pub mod cpu; - pub mod driver; -@@ -181,7 +185,20 @@ +@@ -183,6 +186,17 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -2356,19 +2350,16 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs 14_virtual_mem_p + if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { + panic!("Enabling MMU failed: {}", e); + } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. + + memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. test_main(); - diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs -@@ -27,21 +27,31 @@ +@@ -27,21 +27,29 @@ #[no_mangle] unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; @@ -2386,10 +2377,9 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs 14_virtual_mem_ + if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { + panic!("Enabling MMU failed: {}", e); } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. -+ -+ memory::mmu::post_enable_init(); ++ memory::mmu::post_enable_init(); ++ + // Instantiate and init all device drivers. + if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { + panic!("Error instantiating drivers: {}", x); @@ -2401,11 +2391,10 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs 14_virtual_mem_ } - bsp::driver::driver_manager().post_device_driver_init(); - // println! is usable from here on. -+ // Printing available again from here on. // Let device drivers register and enable their handlers with the interrupt controller. for i in bsp::driver::driver_manager().all_device_drivers() { -@@ -63,13 +73,12 @@ +@@ -63,13 +71,12 @@ /// The main function running after the early init. fn kernel_main() -> ! { use driver::interface::DriverManager; @@ -2421,7 +2410,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs 14_virtual_mem_ let (_, privilege_level) = exception::current_privilege_level(); info!("Current privilege level: {}", privilege_level); -@@ -92,7 +101,7 @@ +@@ -92,7 +99,7 @@ } info!("Registered IRQ handlers:"); @@ -2434,7 +2423,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs 14_virtual_mem_ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_record.rs 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_record.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs -@@ -0,0 +1,249 @@ +@@ -0,0 +1,239 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2020-2022 Andre Richter @@ -2445,7 +2434,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_reco + AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, + Physical, Virtual, +}; -+use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; ++use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; + +//-------------------------------------------------------------------------------------------------- +// Private Definitions @@ -2578,9 +2567,6 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_reco + } + + pub fn print(&self) { -+ const KIB_RSHIFT: u32 = 10; // log2(1024). -+ const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). -+ + info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); + info!( + " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -2595,13 +2581,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_reco + let phys_start = i.phys_start_addr; + let phys_end_inclusive = phys_start + (size - 1); + -+ let (size, unit) = if (size >> MIB_RSHIFT) > 0 { -+ (size >> MIB_RSHIFT, "MiB") -+ } else if (size >> KIB_RSHIFT) > 0 { -+ (size >> KIB_RSHIFT, "KiB") -+ } else { -+ (size, "Byte") -+ }; ++ let (size, unit) = common::size_human_readable_ceil(size); + + let attr = match i.attribute_fields.mem_attributes { + MemAttributes::CacheableDRAM => "C", @@ -2620,8 +2600,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/mapping_reco + }; + + info!( -+ " {}..{} --> {}..{} | \ -+ {: >3} {} | {: <3} {} {: <2} | {}", ++ " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", + virt_start, + virt_end_inclusive, + phys_start, @@ -2735,7 +2714,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/page_alloc.r + } + + /// Initialize the allocator. -+ pub fn initialize(&mut self, pool: MemoryRegion) { ++ pub fn init(&mut self, pool: MemoryRegion) { + if self.pool.is_some() { + warn!("Already initialized"); + return; @@ -3238,7 +3217,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu/types.rs 14_ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs -@@ -3,29 +3,24 @@ +@@ -3,30 +3,24 @@ // Copyright (c) 2020-2022 Andre Richter //! Memory Management Unit. @@ -3262,6 +3241,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua mod translation_table; +mod types; +-use crate::common; -use core::{fmt, ops::RangeInclusive}; +use crate::{ + bsp, @@ -3278,7 +3258,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua //-------------------------------------------------------------------------------------------------- // Public Definitions -@@ -45,13 +40,15 @@ +@@ -46,13 +40,15 @@ /// MMU functions. pub trait MMU { @@ -3297,7 +3277,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua /// Returns true if the MMU is enabled, false otherwise. fn is_enabled(&self) -> bool; -@@ -64,55 +61,51 @@ +@@ -65,55 +61,51 @@ /// Describes properties of an address space. pub struct AddressSpace; @@ -3360,7 +3340,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua +fn kernel_init_mmio_va_allocator() { + let region = bsp::memory::mmu::virt_mmio_remap_region(); + -+ page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); ++ page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +} + +/// Map a region in the kernel's translation tables. @@ -3394,7 +3374,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua } //-------------------------------------------------------------------------------------------------- -@@ -132,6 +125,9 @@ +@@ -133,6 +125,9 @@ /// The granule's size. pub const SIZE: usize = Self::size_checked(); @@ -3404,7 +3384,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua /// The granule's shift, aka log2(size). pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize; -@@ -159,110 +155,147 @@ +@@ -160,98 +155,147 @@ } } @@ -3443,31 +3423,42 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua - let end = *(self.virtual_range)().end(); - let size = end - start + 1; - -- // log2(1024). -- const KIB_RSHIFT: u32 = 10; -- -- // log2(1024 * 1024). -- const MIB_RSHIFT: u32 = 20; +- let (size, unit) = common::size_human_readable_ceil(size); - -- let (size, unit) = if (size >> MIB_RSHIFT) > 0 { -- (size >> MIB_RSHIFT, "MiB") -- } else if (size >> KIB_RSHIFT) > 0 { -- (size >> KIB_RSHIFT, "KiB") -- } else { -- (size, "Byte") -- }; -+ kernel_map_at_unchecked(name, virt_region, phys_region, attr)?; - - let attr = match self.attribute_fields.mem_attributes { - MemAttributes::CacheableDRAM => "C", - MemAttributes::Device => "Dev", - }; -+ Ok(()) -+} - +- - let acc_p = match self.attribute_fields.acc_perms { - AccessPermissions::ReadOnly => "RO", - AccessPermissions::ReadWrite => "RW", +- }; ++ kernel_map_at_unchecked(name, virt_region, phys_region, attr)?; + +- let xn = if self.attribute_fields.execute_never { +- "PXN" +- } else { +- "PX" +- }; +- +- write!( +- f, +- " {:#010x} - {:#010x} | {: >3} {} | {: <3} {} {: <3} | {}", +- start, end, size, unit, attr, acc_p, xn, self.name +- ) +- } ++ Ok(()) + } + +-impl KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> { +- /// Create a new instance. +- pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self { +- Self { +- max_virt_addr_inclusive: max, +- inner: layout, +- } +- } +/// MMIO remapping in the kernel translation tables. +/// +/// Typically used by device drivers. @@ -3492,22 +3483,29 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua + let num_pages = match NonZeroUsize::new(phys_region.num_pages()) { + None => return Err("Requested 0 pages"), + Some(x) => x, - }; ++ }; -- let xn = if self.attribute_fields.execute_never { -- "PXN" -- } else { -- "PX" -- }; +- /// For a virtual address, find and return the physical output address and corresponding +- /// attributes. +- /// +- /// If the address is not found in `inner`, return an identity mapped default with normal +- /// cacheable DRAM attributes. +- pub fn virt_addr_properties( +- &self, +- virt_addr: usize, +- ) -> Result<(usize, AttributeFields), &'static str> { +- if virt_addr > self.max_virt_addr_inclusive { +- return Err("Address out of range"); +- } + let virt_region = + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.alloc(num_pages))?; -- write!( -- f, -- " {:#010x} - {:#010x} | {: >3} {} | {: <3} {} {: <3} | {}", -- start, end, size, unit, attr, acc_p, xn, self.name -- ) -- } +- for i in self.inner.iter() { +- if (i.virtual_range)().contains(&virt_addr) { +- let output_addr = match i.physical_range_translation { +- Translation::Identity => virt_addr, +- Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()), +- }; + kernel_map_at_unchecked( + name, + &virt_region, @@ -3561,37 +3559,8 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs 14_virtua +/// Human-readable print of all recorded kernel mappings. +pub fn kernel_print_mappings() { + mapping_record::kernel_print() - } ++} --impl KernelVirtualLayout<{ NUM_SPECIAL_RANGES }> { -- /// Create a new instance. -- pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL_RANGES]) -> Self { -- Self { -- max_virt_addr_inclusive: max, -- inner: layout, -- } -- } -- -- /// For a virtual address, find and return the physical output address and corresponding -- /// attributes. -- /// -- /// If the address is not found in `inner`, return an identity mapped default with normal -- /// cacheable DRAM attributes. -- pub fn virt_addr_properties( -- &self, -- virt_addr: usize, -- ) -> Result<(usize, AttributeFields), &'static str> { -- if virt_addr > self.max_virt_addr_inclusive { -- return Err("Address out of range"); -- } -- -- for i in self.inner.iter() { -- if (i.virtual_range)().contains(&virt_addr) { -- let output_addr = match i.physical_range_translation { -- Translation::Identity => virt_addr, -- Translation::Offset(a) => a + (virt_addr - (i.virtual_range)().start()), -- }; -- - return Ok((output_addr, i.attribute_fields)); - } - } @@ -3825,7 +3794,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/00_console_sanity.rs #[no_mangle] unsafe fn kernel_init() -> ! { -@@ -19,7 +19,20 @@ +@@ -19,6 +19,17 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -3838,14 +3807,11 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/00_console_sanity.rs + if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { + panic!("Enabling MMU failed: {}", e); + } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. + + memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. // Handshake - assert_eq!(console().read_char(), 'A'); diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/01_timer_sanity.rs 14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/tests/01_timer_sanity.rs @@ -3859,7 +3825,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/01_timer_sanity.rs 14 use test_macros::kernel_test; #[no_mangle] -@@ -19,7 +19,20 @@ +@@ -19,6 +19,17 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -3872,19 +3838,16 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/01_timer_sanity.rs 14 + if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { + panic!("Enabling MMU failed: {}", e); + } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. + + memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. - diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/02_exception_sync_page_fault.rs 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/tests/02_exception_sync_page_fault.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs -@@ -22,18 +22,29 @@ +@@ -22,19 +22,28 @@ #[no_mangle] unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; @@ -3910,19 +3873,18 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/02_exception_sync_pag + info!("Enabling MMU failed: {}", e); cpu::qemu_exit_failure() } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. -+ + + memory::mmu::post_enable_init(); + bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. - ++ info!("Writing beyond mapped area to address 9 GiB..."); let big_addr: u64 = 9 * 1024 * 1024 * 1024; + core::ptr::read_volatile(big_addr as *mut u64); diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/03_exception_restore_sanity.rs 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/tests/03_exception_restore_sanity.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs -@@ -31,18 +31,29 @@ +@@ -31,19 +31,28 @@ #[no_mangle] unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; @@ -3948,19 +3910,18 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/03_exception_restore_ + info!("Enabling MMU failed: {}", e); cpu::qemu_exit_failure() } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. -+ + + memory::mmu::post_enable_init(); + bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. - ++ info!("Making a dummy system call"); + // Calling this inside a function indirectly tests if the link register is restored properly. diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs --- 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs +++ 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs -@@ -10,15 +10,29 @@ +@@ -10,15 +10,27 @@ #![reexport_test_harness_main = "test_main"] #![test_runner(libkernel::test_runner)] @@ -3983,11 +3944,9 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sani + if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { + panic!("Enabling MMU failed: {}", e); + } -+ // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. + + memory::mmu::post_enable_init(); + bsp::driver::driver_manager().qemu_bring_up_console(); -+ // Printing available again from here on. + exception::asynchronous::local_irq_unmask(); diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/common.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/common.rs index 678f4a6c..f32f650f 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/common.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/common.rs @@ -27,3 +27,20 @@ pub const fn align_up(value: usize, alignment: usize) -> usize { (value + alignment - 1) & !(alignment - 1) } + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs index 10c3bedc..2c64d499 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs @@ -20,7 +20,7 @@ pub struct NullConsole; pub static NULL_CONSOLE: NullConsole = NullConsole {}; //-------------------------------------------------------------------------------------------------- -// Private Code +// Public Code //-------------------------------------------------------------------------------------------------- impl interface::Write for NullConsole { diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs index ac57da95..c40cb4e7 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs @@ -114,6 +114,7 @@ #![feature(core_intrinsics)] #![feature(format_args_nl)] #![feature(generic_const_exprs)] +#![feature(int_roundings)] #![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -194,11 +195,9 @@ unsafe fn kernel_init() -> ! { if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { panic!("Enabling MMU failed: {}", e); } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. test_main(); diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/main.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/main.rs index 7574522c..776b28fa 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/main.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/main.rs @@ -38,7 +38,6 @@ unsafe fn kernel_init() -> ! { if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { panic!("Enabling MMU failed: {}", e); } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); @@ -51,7 +50,6 @@ unsafe fn kernel_init() -> ! { panic!("Error loading driver: {}: {}", i.compatible(), x); } } - // Printing available again from here on. // Let device drivers register and enable their handlers with the interrupt controller. for i in bsp::driver::driver_manager().all_device_drivers() { diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs index 43602470..bd1f56ff 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs @@ -81,7 +81,7 @@ use translation_table::interface::TranslationTable; fn kernel_init_mmio_va_allocator() { let region = bsp::memory::mmu::virt_mmio_remap_region(); - page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); } /// Map a region in the kernel's translation tables. diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs index 7d3a6c60..5bc32445 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs @@ -8,7 +8,7 @@ use super::{ AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, Physical, Virtual, }; -use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; +use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -141,9 +141,6 @@ impl MappingRecord { } pub fn print(&self) { - const KIB_RSHIFT: u32 = 10; // log2(1024). - const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). - info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); info!( " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -158,13 +155,7 @@ impl MappingRecord { let phys_start = i.phys_start_addr; let phys_end_inclusive = phys_start + (size - 1); - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match i.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", @@ -183,8 +174,7 @@ impl MappingRecord { }; info!( - " {}..{} --> {}..{} | \ - {: >3} {} | {: <3} {} {: <2} | {}", + " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", virt_start, virt_end_inclusive, phys_start, diff --git a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/page_alloc.rs b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/page_alloc.rs index b4c4232c..347fcd34 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/page_alloc.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/page_alloc.rs @@ -44,7 +44,7 @@ impl PageAllocator { } /// Initialize the allocator. - pub fn initialize(&mut self, pool: MemoryRegion) { + pub fn init(&mut self, pool: MemoryRegion) { if self.pool.is_some() { warn!("Already initialized"); return; diff --git a/14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs b/14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs index a2338d2f..9c6e9cef 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs @@ -28,11 +28,9 @@ unsafe fn kernel_init() -> ! { if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { panic!("Enabling MMU failed: {}", e); } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. // Handshake assert_eq!(console().read_char(), 'A'); diff --git a/14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs b/14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs index 4b4e90e4..dc3337e2 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs @@ -28,11 +28,9 @@ unsafe fn kernel_init() -> ! { if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { panic!("Enabling MMU failed: {}", e); } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. diff --git a/14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs b/14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs index 209517ac..594ffb40 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs @@ -40,11 +40,9 @@ unsafe fn kernel_init() -> ! { info!("Enabling MMU failed: {}", e); cpu::qemu_exit_failure() } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. info!("Writing beyond mapped area to address 9 GiB..."); let big_addr: u64 = 9 * 1024 * 1024 * 1024; diff --git a/14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs b/14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs index babc31e2..32001b2a 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs @@ -49,11 +49,9 @@ unsafe fn kernel_init() -> ! { info!("Enabling MMU failed: {}", e); cpu::qemu_exit_failure() } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. info!("Making a dummy system call"); diff --git a/14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs b/14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs index 872cc008..7a344874 100644 --- a/14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs +++ b/14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs @@ -27,11 +27,9 @@ unsafe fn kernel_init() -> ! { if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { panic!("Enabling MMU failed: {}", e); } - // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. memory::mmu::post_enable_init(); bsp::driver::driver_manager().qemu_bring_up_console(); - // Printing available again from here on. exception::asynchronous::local_irq_unmask(); diff --git a/15_virtual_mem_part3_precomputed_tables/README.md b/15_virtual_mem_part3_precomputed_tables/README.md index 5a07f34b..186acc2a 100644 --- a/15_virtual_mem_part3_precomputed_tables/README.md +++ b/15_virtual_mem_part3_precomputed_tables/README.md @@ -1315,7 +1315,7 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi/memory/mmu. diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs 15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs --- 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs -@@ -185,20 +185,8 @@ +@@ -186,17 +186,7 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -1328,19 +1328,17 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs 15_virtual_mem_part3 - if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { - panic!("Enabling MMU failed: {}", e); - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); +- memory::mmu::post_enable_init(); ++ memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. test_main(); - diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs 15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs --- 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs -@@ -17,29 +17,17 @@ +@@ -17,29 +17,18 @@ /// Early init code. /// @@ -1368,20 +1366,13 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs 15_virtual_mem_part - if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { - panic!("Enabling MMU failed: {}", e); - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); +- memory::mmu::post_enable_init(); ++ memory::init(); // Instantiate and init all device drivers. -@@ -51,7 +39,6 @@ - panic!("Error loading driver: {}: {}", i.compatible(), x); - } - } -- // Printing available again from here on. - - // Let device drivers register and enable their handlers with the interrupt controller. - for i in bsp::driver::driver_manager().all_device_drivers() { -@@ -60,6 +47,8 @@ + if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { +@@ -58,6 +47,8 @@ } } @@ -1494,7 +1485,7 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me }; use core::{fmt, num::NonZeroUsize}; -@@ -73,7 +74,7 @@ +@@ -73,17 +74,9 @@ // Private Code //-------------------------------------------------------------------------------------------------- use interface::MMU; @@ -1502,8 +1493,18 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me +use synchronization::interface::ReadWriteEx; use translation_table::interface::TranslationTable; - /// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's -@@ -101,13 +102,21 @@ +-/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's +-/// MMIO VA allocator with it. +-fn kernel_init_mmio_va_allocator() { +- let region = bsp::memory::mmu::virt_mmio_remap_region(); +- +- page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +-} +- + /// Map a region in the kernel's translation tables. + /// + /// No input checks done, input is passed through to the architectural implementation. +@@ -101,13 +94,21 @@ bsp::memory::mmu::kernel_translation_tables() .write(|tables| tables.map_at(virt_region, phys_region, attr))?; @@ -1528,7 +1529,7 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me //-------------------------------------------------------------------------------------------------- // Public Code //-------------------------------------------------------------------------------------------------- -@@ -155,27 +164,16 @@ +@@ -155,27 +156,24 @@ } } @@ -1541,6 +1542,14 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me -/// - See `kernel_map_at_unchecked()`. -/// - Does not prevent aliasing. Currently, the callers must be trusted. -pub unsafe fn kernel_map_at( ++/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's ++/// MMIO VA allocator with it. ++pub fn kernel_init_mmio_va_allocator() { ++ let region = bsp::memory::mmu::virt_mmio_remap_region(); ++ ++ page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); ++} ++ +/// Add an entry to the mapping info record. +pub fn kernel_add_mapping_record( name: &'static str, @@ -1561,15 +1570,15 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me } /// MMIO remapping in the kernel translation tables. -@@ -224,21 +222,24 @@ +@@ -224,21 +222,29 @@ Ok(virt_addr + offset_into_start_page) } -/// Map the kernel's binary. Returns the translation table's base address. +-/// +-/// # Safety +/// Try to translate a kernel virtual page address to a physical page address. /// --/// # Safety --/// -/// - See [`bsp::memory::mmu::kernel_map_binary()`]. -pub unsafe fn kernel_map_binary() -> Result, &'static str> { - let phys_kernel_tables_base_addr = @@ -1577,8 +1586,6 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me - tables.init(); - tables.phys_base_address() - }); -- -- bsp::memory::mmu::kernel_map_binary()?; +/// Will only succeed if there exists a valid mapping for the input page. +pub fn try_kernel_virt_page_addr_to_phys_page_addr( + virt_page_addr: PageAddress, @@ -1587,7 +1594,7 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me + .read(|tables| tables.try_virt_page_addr_to_phys_page_addr(virt_page_addr)) +} -- Ok(phys_kernel_tables_base_addr) +- bsp::memory::mmu::kernel_map_binary()?; +/// Try to get the attributes of a kernel page. +/// +/// Will only succeed if there exists a valid mapping for the input page. @@ -1596,10 +1603,16 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me +) -> Result { + bsp::memory::mmu::kernel_translation_tables() + .read(|tables| tables.try_page_attributes(virt_page_addr)) ++} + +- Ok(phys_kernel_tables_base_addr) ++/// Human-readable print of all recorded kernel mappings. ++pub fn kernel_print_mappings() { ++ mapping_record::kernel_print() } /// Enable the MMU and data + instruction caching. -@@ -246,6 +247,7 @@ +@@ -246,56 +252,9 @@ /// # Safety /// /// - Crucial function during kernel init. Changes the the complete memory view of the processor. @@ -1607,11 +1620,19 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me pub unsafe fn enable_mmu_and_caching( phys_tables_base_addr: Address, ) -> Result<(), MMUEnableError> { -@@ -261,41 +263,3 @@ - pub fn kernel_print_mappings() { - mapping_record::kernel_print() + arch_mmu::mmu().enable_mmu_and_caching(phys_tables_base_addr) } - +-/// Finish initialization of the MMU subsystem. +-pub fn post_enable_init() { +- kernel_init_mmio_va_allocator(); +-} +- +-/// Human-readable print of all recorded kernel mappings. +-pub fn kernel_print_mappings() { +- mapping_record::kernel_print() +-} +- -//-------------------------------------------------------------------------------------------------- -// Testing -//-------------------------------------------------------------------------------------------------- @@ -1650,10 +1671,26 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs 15_virtual_me - } -} +diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/src/memory.rs 15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs +--- 14_virtual_mem_part2_mmio_remap/kernel/src/memory.rs ++++ 15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs +@@ -136,6 +136,11 @@ + } + } + ++/// Initialize the memory subsystem. ++pub fn init() { ++ mmu::kernel_init_mmio_va_allocator(); ++} ++ + //-------------------------------------------------------------------------------------------------- + // Testing + //-------------------------------------------------------------------------------------------------- + diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs 15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs --- 14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs -@@ -19,20 +19,8 @@ +@@ -19,17 +19,7 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -1666,19 +1703,17 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs 15_v - if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { - panic!("Enabling MMU failed: {}", e); - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); +- memory::mmu::post_enable_init(); ++ memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. // Handshake - assert_eq!(console().read_char(), 'A'); diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs 15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs --- 14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs -@@ -19,20 +19,8 @@ +@@ -19,17 +19,7 @@ use driver::interface::DriverManager; exception::handling_init(); @@ -1691,23 +1726,21 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs 15_vir - if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { - panic!("Enabling MMU failed: {}", e); - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); +- memory::mmu::post_enable_init(); ++ memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. - diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs 15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs --- 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs -@@ -24,28 +24,12 @@ +@@ -24,26 +24,12 @@ use driver::interface::DriverManager; exception::handling_init(); -+ memory::mmu::post_enable_init(); ++ memory::init(); + bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. @@ -1725,11 +1758,9 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fa - info!("Enabling MMU failed: {}", e); - cpu::qemu_exit_failure() - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); - bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. - info!("Writing beyond mapped area to address 9 GiB..."); let big_addr: u64 = 9 * 1024 * 1024 * 1024; @@ -1738,11 +1769,11 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fa diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs 15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs --- 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs -@@ -33,28 +33,12 @@ +@@ -33,26 +33,12 @@ use driver::interface::DriverManager; exception::handling_init(); -+ memory::mmu::post_enable_init(); ++ memory::init(); + bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. @@ -1760,11 +1791,9 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sani - info!("Enabling MMU failed: {}", e); - cpu::qemu_exit_failure() - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); - bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. - info!("Making a dummy system call"); @@ -1773,7 +1802,7 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sani diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs 15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs --- 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs +++ 15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs -@@ -17,22 +17,10 @@ +@@ -17,20 +17,10 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; @@ -1787,11 +1816,10 @@ diff -uNr 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.r - if let Err(e) = memory::mmu::enable_mmu_and_caching(phys_kernel_tables_base_addr) { - panic!("Enabling MMU failed: {}", e); - } -- // Printing will silently fail from here on, because the driver's MMIO is not remapped yet. - - memory::mmu::post_enable_init(); +- memory::mmu::post_enable_init(); ++ memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); -- // Printing available again from here on. + exception::handling_init(); exception::asynchronous::local_irq_unmask(); diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/common.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/common.rs index 678f4a6c..f32f650f 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/common.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/common.rs @@ -27,3 +27,20 @@ pub const fn align_up(value: usize, alignment: usize) -> usize { (value + alignment - 1) & !(alignment - 1) } + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/console/null_console.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/console/null_console.rs index 10c3bedc..2c64d499 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/console/null_console.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/console/null_console.rs @@ -20,7 +20,7 @@ pub struct NullConsole; pub static NULL_CONSOLE: NullConsole = NullConsole {}; //-------------------------------------------------------------------------------------------------- -// Private Code +// Public Code //-------------------------------------------------------------------------------------------------- impl interface::Write for NullConsole { diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs index 1787ce02..a9577868 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs @@ -114,6 +114,7 @@ #![feature(core_intrinsics)] #![feature(format_args_nl)] #![feature(generic_const_exprs)] +#![feature(int_roundings)] #![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -185,7 +186,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); test_main(); diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs index 928f12c2..9aeb4438 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/main.rs @@ -28,7 +28,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); // Instantiate and init all device drivers. if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs index 64d8cf64..3b6868e7 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory.rs @@ -136,6 +136,11 @@ impl fmt::Display for Address { } } +/// Initialize the memory subsystem. +pub fn init() { + mmu::kernel_init_mmio_va_allocator(); +} + //-------------------------------------------------------------------------------------------------- // Testing //-------------------------------------------------------------------------------------------------- diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu.rs index c6461474..698f2095 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu.rs @@ -77,14 +77,6 @@ use interface::MMU; use synchronization::interface::ReadWriteEx; use translation_table::interface::TranslationTable; -/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's -/// MMIO VA allocator with it. -fn kernel_init_mmio_va_allocator() { - let region = bsp::memory::mmu::virt_mmio_remap_region(); - - page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); -} - /// Map a region in the kernel's translation tables. /// /// No input checks done, input is passed through to the architectural implementation. @@ -164,6 +156,14 @@ impl AddressSpace { } } +/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's +/// MMIO VA allocator with it. +pub fn kernel_init_mmio_va_allocator() { + let region = bsp::memory::mmu::virt_mmio_remap_region(); + + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +} + /// Add an entry to the mapping info record. pub fn kernel_add_mapping_record( name: &'static str, @@ -242,6 +242,11 @@ pub fn try_kernel_page_attributes( .read(|tables| tables.try_page_attributes(virt_page_addr)) } +/// Human-readable print of all recorded kernel mappings. +pub fn kernel_print_mappings() { + mapping_record::kernel_print() +} + /// Enable the MMU and data + instruction caching. /// /// # Safety @@ -253,13 +258,3 @@ pub unsafe fn enable_mmu_and_caching( ) -> Result<(), MMUEnableError> { arch_mmu::mmu().enable_mmu_and_caching(phys_tables_base_addr) } - -/// Finish initialization of the MMU subsystem. -pub fn post_enable_init() { - kernel_init_mmio_va_allocator(); -} - -/// Human-readable print of all recorded kernel mappings. -pub fn kernel_print_mappings() { - mapping_record::kernel_print() -} diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/mapping_record.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/mapping_record.rs index 7d3a6c60..5bc32445 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/mapping_record.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/mapping_record.rs @@ -8,7 +8,7 @@ use super::{ AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, Physical, Virtual, }; -use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; +use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -141,9 +141,6 @@ impl MappingRecord { } pub fn print(&self) { - const KIB_RSHIFT: u32 = 10; // log2(1024). - const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). - info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); info!( " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -158,13 +155,7 @@ impl MappingRecord { let phys_start = i.phys_start_addr; let phys_end_inclusive = phys_start + (size - 1); - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match i.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", @@ -183,8 +174,7 @@ impl MappingRecord { }; info!( - " {}..{} --> {}..{} | \ - {: >3} {} | {: <3} {} {: <2} | {}", + " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", virt_start, virt_end_inclusive, phys_start, diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/page_alloc.rs b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/page_alloc.rs index b4c4232c..347fcd34 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/page_alloc.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/src/memory/mmu/page_alloc.rs @@ -44,7 +44,7 @@ impl PageAllocator { } /// Initialize the allocator. - pub fn initialize(&mut self, pool: MemoryRegion) { + pub fn init(&mut self, pool: MemoryRegion) { if self.pool.is_some() { warn!("Already initialized"); return; diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs b/15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs index f2a1f3ed..305510ce 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/tests/00_console_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Handshake diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs b/15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs index caeca3cd..d5d76a5c 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/tests/01_timer_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs b/15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs index feb84d9b..ec7a365a 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/tests/02_exception_sync_page_fault.rs @@ -24,7 +24,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs b/15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs index a521a871..47dd2714 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/tests/03_exception_restore_sanity.rs @@ -33,7 +33,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs b/15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs index cd2d29d6..7b9628d5 100644 --- a/15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs +++ b/15_virtual_mem_part3_precomputed_tables/kernel/tests/04_exception_irq_sanity.rs @@ -17,7 +17,7 @@ use test_macros::kernel_test; unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); exception::handling_init(); diff --git a/16_virtual_mem_part4_higher_half_kernel/README.md b/16_virtual_mem_part4_higher_half_kernel/README.md index 943273c0..0a30a2aa 100644 --- a/16_virtual_mem_part4_higher_half_kernel/README.md +++ b/16_virtual_mem_part4_higher_half_kernel/README.md @@ -729,7 +729,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/raspberrypi/mem diff -uNr 15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs 16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs --- 15_virtual_mem_part3_precomputed_tables/kernel/src/lib.rs +++ 16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs -@@ -153,11 +153,6 @@ +@@ -154,11 +154,6 @@ ) } diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/common.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/common.rs index 678f4a6c..f32f650f 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/common.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/common.rs @@ -27,3 +27,20 @@ pub const fn align_up(value: usize, alignment: usize) -> usize { (value + alignment - 1) & !(alignment - 1) } + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/console/null_console.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/console/null_console.rs index 10c3bedc..2c64d499 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/console/null_console.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/console/null_console.rs @@ -20,7 +20,7 @@ pub struct NullConsole; pub static NULL_CONSOLE: NullConsole = NullConsole {}; //-------------------------------------------------------------------------------------------------- -// Private Code +// Public Code //-------------------------------------------------------------------------------------------------- impl interface::Write for NullConsole { diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs index f023d683..1483c5a3 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs @@ -114,6 +114,7 @@ #![feature(core_intrinsics)] #![feature(format_args_nl)] #![feature(generic_const_exprs)] +#![feature(int_roundings)] #![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -180,7 +181,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); test_main(); diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/main.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/main.rs index 928f12c2..9aeb4438 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/main.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/main.rs @@ -28,7 +28,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); // Instantiate and init all device drivers. if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory.rs index 64d8cf64..3b6868e7 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory.rs @@ -136,6 +136,11 @@ impl fmt::Display for Address { } } +/// Initialize the memory subsystem. +pub fn init() { + mmu::kernel_init_mmio_va_allocator(); +} + //-------------------------------------------------------------------------------------------------- // Testing //-------------------------------------------------------------------------------------------------- diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu.rs index 8806a993..7f02dad9 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu.rs @@ -82,14 +82,6 @@ use interface::MMU; use synchronization::interface::ReadWriteEx; use translation_table::interface::TranslationTable; -/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's -/// MMIO VA allocator with it. -fn kernel_init_mmio_va_allocator() { - let region = bsp::memory::mmu::virt_mmio_remap_region(); - - page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); -} - /// Map a region in the kernel's translation tables. /// /// No input checks done, input is passed through to the architectural implementation. @@ -169,6 +161,14 @@ impl AddressSpace { } } +/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's +/// MMIO VA allocator with it. +pub fn kernel_init_mmio_va_allocator() { + let region = bsp::memory::mmu::virt_mmio_remap_region(); + + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +} + /// Add an entry to the mapping info record. pub fn kernel_add_mapping_record( name: &'static str, @@ -247,6 +247,11 @@ pub fn try_kernel_page_attributes( .read(|tables| tables.try_page_attributes(virt_page_addr)) } +/// Human-readable print of all recorded kernel mappings. +pub fn kernel_print_mappings() { + mapping_record::kernel_print() +} + /// Enable the MMU and data + instruction caching. /// /// # Safety @@ -258,13 +263,3 @@ pub unsafe fn enable_mmu_and_caching( ) -> Result<(), MMUEnableError> { arch_mmu::mmu().enable_mmu_and_caching(phys_tables_base_addr) } - -/// Finish initialization of the MMU subsystem. -pub fn post_enable_init() { - kernel_init_mmio_va_allocator(); -} - -/// Human-readable print of all recorded kernel mappings. -pub fn kernel_print_mappings() { - mapping_record::kernel_print() -} diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/mapping_record.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/mapping_record.rs index 7d3a6c60..5bc32445 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/mapping_record.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/mapping_record.rs @@ -8,7 +8,7 @@ use super::{ AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, Physical, Virtual, }; -use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; +use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -141,9 +141,6 @@ impl MappingRecord { } pub fn print(&self) { - const KIB_RSHIFT: u32 = 10; // log2(1024). - const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). - info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); info!( " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -158,13 +155,7 @@ impl MappingRecord { let phys_start = i.phys_start_addr; let phys_end_inclusive = phys_start + (size - 1); - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match i.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", @@ -183,8 +174,7 @@ impl MappingRecord { }; info!( - " {}..{} --> {}..{} | \ - {: >3} {} | {: <3} {} {: <2} | {}", + " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", virt_start, virt_end_inclusive, phys_start, diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/page_alloc.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/page_alloc.rs index b4c4232c..347fcd34 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/page_alloc.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/src/memory/mmu/page_alloc.rs @@ -44,7 +44,7 @@ impl PageAllocator { } /// Initialize the allocator. - pub fn initialize(&mut self, pool: MemoryRegion) { + pub fn init(&mut self, pool: MemoryRegion) { if self.pool.is_some() { warn!("Already initialized"); return; diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/00_console_sanity.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/00_console_sanity.rs index f2a1f3ed..305510ce 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/00_console_sanity.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/00_console_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Handshake diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/01_timer_sanity.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/01_timer_sanity.rs index caeca3cd..d5d76a5c 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/01_timer_sanity.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/01_timer_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/02_exception_sync_page_fault.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/02_exception_sync_page_fault.rs index 33463e0a..a6d15b69 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/02_exception_sync_page_fault.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/02_exception_sync_page_fault.rs @@ -24,7 +24,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/03_exception_restore_sanity.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/03_exception_restore_sanity.rs index a521a871..47dd2714 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/03_exception_restore_sanity.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/03_exception_restore_sanity.rs @@ -33,7 +33,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/04_exception_irq_sanity.rs b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/04_exception_irq_sanity.rs index cd2d29d6..7b9628d5 100644 --- a/16_virtual_mem_part4_higher_half_kernel/kernel/tests/04_exception_irq_sanity.rs +++ b/16_virtual_mem_part4_higher_half_kernel/kernel/tests/04_exception_irq_sanity.rs @@ -17,7 +17,7 @@ use test_macros::kernel_test; unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); exception::handling_init(); diff --git a/17_kernel_symbols/README.md b/17_kernel_symbols/README.md index 84378fff..d3b42b65 100644 --- a/17_kernel_symbols/README.md +++ b/17_kernel_symbols/README.md @@ -332,7 +332,7 @@ diff -uNr 16_virtual_mem_part4_higher_half_kernel/kernel/src/bsp/raspberrypi/mem diff -uNr 16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs 17_kernel_symbols/kernel/src/lib.rs --- 16_virtual_mem_part4_higher_half_kernel/kernel/src/lib.rs +++ 17_kernel_symbols/kernel/src/lib.rs -@@ -138,6 +138,7 @@ +@@ -139,6 +139,7 @@ pub mod memory; pub mod print; pub mod state; diff --git a/17_kernel_symbols/kernel/src/common.rs b/17_kernel_symbols/kernel/src/common.rs index 678f4a6c..f32f650f 100644 --- a/17_kernel_symbols/kernel/src/common.rs +++ b/17_kernel_symbols/kernel/src/common.rs @@ -27,3 +27,20 @@ pub const fn align_up(value: usize, alignment: usize) -> usize { (value + alignment - 1) & !(alignment - 1) } + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/17_kernel_symbols/kernel/src/console/null_console.rs b/17_kernel_symbols/kernel/src/console/null_console.rs index 10c3bedc..2c64d499 100644 --- a/17_kernel_symbols/kernel/src/console/null_console.rs +++ b/17_kernel_symbols/kernel/src/console/null_console.rs @@ -20,7 +20,7 @@ pub struct NullConsole; pub static NULL_CONSOLE: NullConsole = NullConsole {}; //-------------------------------------------------------------------------------------------------- -// Private Code +// Public Code //-------------------------------------------------------------------------------------------------- impl interface::Write for NullConsole { diff --git a/17_kernel_symbols/kernel/src/lib.rs b/17_kernel_symbols/kernel/src/lib.rs index e70468e5..1f6d11b1 100644 --- a/17_kernel_symbols/kernel/src/lib.rs +++ b/17_kernel_symbols/kernel/src/lib.rs @@ -114,6 +114,7 @@ #![feature(core_intrinsics)] #![feature(format_args_nl)] #![feature(generic_const_exprs)] +#![feature(int_roundings)] #![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -181,7 +182,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); test_main(); diff --git a/17_kernel_symbols/kernel/src/main.rs b/17_kernel_symbols/kernel/src/main.rs index 928f12c2..9aeb4438 100644 --- a/17_kernel_symbols/kernel/src/main.rs +++ b/17_kernel_symbols/kernel/src/main.rs @@ -28,7 +28,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); // Instantiate and init all device drivers. if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { diff --git a/17_kernel_symbols/kernel/src/memory.rs b/17_kernel_symbols/kernel/src/memory.rs index 64d8cf64..3b6868e7 100644 --- a/17_kernel_symbols/kernel/src/memory.rs +++ b/17_kernel_symbols/kernel/src/memory.rs @@ -136,6 +136,11 @@ impl fmt::Display for Address { } } +/// Initialize the memory subsystem. +pub fn init() { + mmu::kernel_init_mmio_va_allocator(); +} + //-------------------------------------------------------------------------------------------------- // Testing //-------------------------------------------------------------------------------------------------- diff --git a/17_kernel_symbols/kernel/src/memory/mmu.rs b/17_kernel_symbols/kernel/src/memory/mmu.rs index 8806a993..7f02dad9 100644 --- a/17_kernel_symbols/kernel/src/memory/mmu.rs +++ b/17_kernel_symbols/kernel/src/memory/mmu.rs @@ -82,14 +82,6 @@ use interface::MMU; use synchronization::interface::ReadWriteEx; use translation_table::interface::TranslationTable; -/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's -/// MMIO VA allocator with it. -fn kernel_init_mmio_va_allocator() { - let region = bsp::memory::mmu::virt_mmio_remap_region(); - - page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); -} - /// Map a region in the kernel's translation tables. /// /// No input checks done, input is passed through to the architectural implementation. @@ -169,6 +161,14 @@ impl AddressSpace { } } +/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's +/// MMIO VA allocator with it. +pub fn kernel_init_mmio_va_allocator() { + let region = bsp::memory::mmu::virt_mmio_remap_region(); + + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +} + /// Add an entry to the mapping info record. pub fn kernel_add_mapping_record( name: &'static str, @@ -247,6 +247,11 @@ pub fn try_kernel_page_attributes( .read(|tables| tables.try_page_attributes(virt_page_addr)) } +/// Human-readable print of all recorded kernel mappings. +pub fn kernel_print_mappings() { + mapping_record::kernel_print() +} + /// Enable the MMU and data + instruction caching. /// /// # Safety @@ -258,13 +263,3 @@ pub unsafe fn enable_mmu_and_caching( ) -> Result<(), MMUEnableError> { arch_mmu::mmu().enable_mmu_and_caching(phys_tables_base_addr) } - -/// Finish initialization of the MMU subsystem. -pub fn post_enable_init() { - kernel_init_mmio_va_allocator(); -} - -/// Human-readable print of all recorded kernel mappings. -pub fn kernel_print_mappings() { - mapping_record::kernel_print() -} diff --git a/17_kernel_symbols/kernel/src/memory/mmu/mapping_record.rs b/17_kernel_symbols/kernel/src/memory/mmu/mapping_record.rs index 7d3a6c60..5bc32445 100644 --- a/17_kernel_symbols/kernel/src/memory/mmu/mapping_record.rs +++ b/17_kernel_symbols/kernel/src/memory/mmu/mapping_record.rs @@ -8,7 +8,7 @@ use super::{ AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, Physical, Virtual, }; -use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; +use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -141,9 +141,6 @@ impl MappingRecord { } pub fn print(&self) { - const KIB_RSHIFT: u32 = 10; // log2(1024). - const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). - info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); info!( " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -158,13 +155,7 @@ impl MappingRecord { let phys_start = i.phys_start_addr; let phys_end_inclusive = phys_start + (size - 1); - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match i.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", @@ -183,8 +174,7 @@ impl MappingRecord { }; info!( - " {}..{} --> {}..{} | \ - {: >3} {} | {: <3} {} {: <2} | {}", + " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", virt_start, virt_end_inclusive, phys_start, diff --git a/17_kernel_symbols/kernel/src/memory/mmu/page_alloc.rs b/17_kernel_symbols/kernel/src/memory/mmu/page_alloc.rs index b4c4232c..347fcd34 100644 --- a/17_kernel_symbols/kernel/src/memory/mmu/page_alloc.rs +++ b/17_kernel_symbols/kernel/src/memory/mmu/page_alloc.rs @@ -44,7 +44,7 @@ impl PageAllocator { } /// Initialize the allocator. - pub fn initialize(&mut self, pool: MemoryRegion) { + pub fn init(&mut self, pool: MemoryRegion) { if self.pool.is_some() { warn!("Already initialized"); return; diff --git a/17_kernel_symbols/kernel/tests/00_console_sanity.rs b/17_kernel_symbols/kernel/tests/00_console_sanity.rs index f2a1f3ed..305510ce 100644 --- a/17_kernel_symbols/kernel/tests/00_console_sanity.rs +++ b/17_kernel_symbols/kernel/tests/00_console_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Handshake diff --git a/17_kernel_symbols/kernel/tests/01_timer_sanity.rs b/17_kernel_symbols/kernel/tests/01_timer_sanity.rs index caeca3cd..d5d76a5c 100644 --- a/17_kernel_symbols/kernel/tests/01_timer_sanity.rs +++ b/17_kernel_symbols/kernel/tests/01_timer_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. diff --git a/17_kernel_symbols/kernel/tests/02_exception_sync_page_fault.rs b/17_kernel_symbols/kernel/tests/02_exception_sync_page_fault.rs index 33463e0a..a6d15b69 100644 --- a/17_kernel_symbols/kernel/tests/02_exception_sync_page_fault.rs +++ b/17_kernel_symbols/kernel/tests/02_exception_sync_page_fault.rs @@ -24,7 +24,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/17_kernel_symbols/kernel/tests/03_exception_restore_sanity.rs b/17_kernel_symbols/kernel/tests/03_exception_restore_sanity.rs index a521a871..47dd2714 100644 --- a/17_kernel_symbols/kernel/tests/03_exception_restore_sanity.rs +++ b/17_kernel_symbols/kernel/tests/03_exception_restore_sanity.rs @@ -33,7 +33,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/17_kernel_symbols/kernel/tests/04_exception_irq_sanity.rs b/17_kernel_symbols/kernel/tests/04_exception_irq_sanity.rs index cd2d29d6..7b9628d5 100644 --- a/17_kernel_symbols/kernel/tests/04_exception_irq_sanity.rs +++ b/17_kernel_symbols/kernel/tests/04_exception_irq_sanity.rs @@ -17,7 +17,7 @@ use test_macros::kernel_test; unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); exception::handling_init(); diff --git a/18_backtrace/README.md b/18_backtrace/README.md index fd173703..2c4dc127 100644 --- a/18_backtrace/README.md +++ b/18_backtrace/README.md @@ -727,7 +727,7 @@ diff -uNr 17_kernel_symbols/kernel/src/_arch/aarch64/exception.s 18_backtrace/ke diff -uNr 17_kernel_symbols/kernel/src/backtrace.rs 18_backtrace/kernel/src/backtrace.rs --- 17_kernel_symbols/kernel/src/backtrace.rs +++ 18_backtrace/kernel/src/backtrace.rs -@@ -0,0 +1,112 @@ +@@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2022 Andre Richter @@ -790,7 +790,9 @@ diff -uNr 17_kernel_symbols/kernel/src/backtrace.rs 18_backtrace/kernel/src/back + |maybe_iter: Option<&mut dyn Iterator>| match maybe_iter { + None => fmt_res = writeln!(f, "ERROR! No valid stack frame found"), + Some(iter) => { -+ for (i, backtrace_res) in iter.enumerate() { ++ // Since the backtrace is printed, the first function is always ++ // core::fmt::write. Skip 1 so it is excluded and doesn't bloat the output. ++ for (i, backtrace_res) in iter.skip(1).enumerate() { + match backtrace_res { + BacktraceItem::InvalidFramePointer(addr) => { + fmt_res = writeln!( @@ -909,7 +911,7 @@ diff -uNr 17_kernel_symbols/kernel/src/bsp/raspberrypi/memory/mmu.rs 18_backtrac diff -uNr 17_kernel_symbols/kernel/src/lib.rs 18_backtrace/kernel/src/lib.rs --- 17_kernel_symbols/kernel/src/lib.rs +++ 18_backtrace/kernel/src/lib.rs -@@ -129,6 +129,7 @@ +@@ -130,6 +130,7 @@ mod panic_wait; mod synchronization; @@ -1062,7 +1064,7 @@ diff -uNr 17_kernel_symbols/kernel/tests/05_backtrace_sanity.rs 18_backtrace/ker + use driver::interface::DriverManager; + + exception::handling_init(); -+ memory::mmu::post_enable_init(); ++ memory::init(); + bsp::driver::driver_manager().qemu_bring_up_console(); + + nested(); @@ -1133,7 +1135,7 @@ diff -uNr 17_kernel_symbols/kernel/tests/06_backtrace_invalid_frame.rs 18_backtr + use driver::interface::DriverManager; + + exception::handling_init(); -+ memory::mmu::post_enable_init(); ++ memory::init(); + bsp::driver::driver_manager().qemu_bring_up_console(); + + nested(); @@ -1208,7 +1210,7 @@ diff -uNr 17_kernel_symbols/kernel/tests/07_backtrace_invalid_link.rs 18_backtra + use driver::interface::DriverManager; + + exception::handling_init(); -+ memory::mmu::post_enable_init(); ++ memory::init(); + bsp::driver::driver_manager().qemu_bring_up_console(); + + nested_1(); @@ -1264,4 +1266,50 @@ diff -uNr 17_kernel_symbols/Makefile 18_backtrace/Makefile $(call color_header, "Launching GDB") @$(DOCKER_GDB) gdb-multiarch -q $(KERNEL_ELF) +diff -uNr 17_kernel_symbols/tools/translation_table_tool/bsp.rb 18_backtrace/tools/translation_table_tool/bsp.rb +--- 17_kernel_symbols/tools/translation_table_tool/bsp.rb ++++ 18_backtrace/tools/translation_table_tool/bsp.rb +@@ -45,6 +45,10 @@ + raise + end + +- x.scan(/\d+/).join.to_i(16) ++ # Extract the hex literal with underscores like 0x0123_abcd. ++ x = x.scan(/0x[\h_]*/)[0] ++ ++ # Further remove x and _ and convert to int. ++ x.scan(/\h+/).join.to_i(16) + end + end + +diff -uNr 17_kernel_symbols/tools/translation_table_tool/generic.rb 18_backtrace/tools/translation_table_tool/generic.rb +--- 17_kernel_symbols/tools/translation_table_tool/generic.rb ++++ 18_backtrace/tools/translation_table_tool/generic.rb +@@ -109,13 +109,23 @@ + @attributes = attributes + end + ++ def size_human_readable(size) ++ if size >= (1024 * 1024) ++ "#{(size / (1024 * 1024)).to_s.rjust(3)} MiB" ++ elsif size >= 1024 ++ "#{(size / 1024).to_s.rjust(3)} KiB" ++ else ++ raise ++ end ++ end ++ + def to_s + name = @name.ljust(self.class.max_section_name_length) + virt_start = @virt_region.first.to_hex_underscore(with_leading_zeros: true) + phys_start = @phys_region.first.to_hex_underscore(with_leading_zeros: true) +- size = ((@virt_region.size * 65_536) / 1024).to_s.rjust(3) ++ size = size_human_readable(@virt_region.size * 65_536) + +- "#{name} | #{virt_start} | #{phys_start} | #{size} KiB | #{@attributes}" ++ "#{name} | #{virt_start} | #{phys_start} | #{size} | #{@attributes}" + end + + def self.print_divider + ``` diff --git a/18_backtrace/kernel/src/backtrace.rs b/18_backtrace/kernel/src/backtrace.rs index 7dba2e4a..22de6c48 100644 --- a/18_backtrace/kernel/src/backtrace.rs +++ b/18_backtrace/kernel/src/backtrace.rs @@ -60,7 +60,9 @@ impl fmt::Display for Backtrace { |maybe_iter: Option<&mut dyn Iterator>| match maybe_iter { None => fmt_res = writeln!(f, "ERROR! No valid stack frame found"), Some(iter) => { - for (i, backtrace_res) in iter.enumerate() { + // Since the backtrace is printed, the first function is always + // core::fmt::write. Skip 1 so it is excluded and doesn't bloat the output. + for (i, backtrace_res) in iter.skip(1).enumerate() { match backtrace_res { BacktraceItem::InvalidFramePointer(addr) => { fmt_res = writeln!( diff --git a/18_backtrace/kernel/src/common.rs b/18_backtrace/kernel/src/common.rs index 678f4a6c..f32f650f 100644 --- a/18_backtrace/kernel/src/common.rs +++ b/18_backtrace/kernel/src/common.rs @@ -27,3 +27,20 @@ pub const fn align_up(value: usize, alignment: usize) -> usize { (value + alignment - 1) & !(alignment - 1) } + +/// Convert a size into human readable format. +pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static str) { + const KIB: usize = 1024; + const MIB: usize = 1024 * 1024; + const GIB: usize = 1024 * 1024 * 1024; + + if (size / GIB) > 0 { + (size.div_ceil(GIB), "GiB") + } else if (size / MIB) > 0 { + (size.div_ceil(MIB), "MiB") + } else if (size / KIB) > 0 { + (size.div_ceil(KIB), "KiB") + } else { + (size, "Byte") + } +} diff --git a/18_backtrace/kernel/src/console/null_console.rs b/18_backtrace/kernel/src/console/null_console.rs index 10c3bedc..2c64d499 100644 --- a/18_backtrace/kernel/src/console/null_console.rs +++ b/18_backtrace/kernel/src/console/null_console.rs @@ -20,7 +20,7 @@ pub struct NullConsole; pub static NULL_CONSOLE: NullConsole = NullConsole {}; //-------------------------------------------------------------------------------------------------- -// Private Code +// Public Code //-------------------------------------------------------------------------------------------------- impl interface::Write for NullConsole { diff --git a/18_backtrace/kernel/src/lib.rs b/18_backtrace/kernel/src/lib.rs index 688fc1a4..2c13a342 100644 --- a/18_backtrace/kernel/src/lib.rs +++ b/18_backtrace/kernel/src/lib.rs @@ -114,6 +114,7 @@ #![feature(core_intrinsics)] #![feature(format_args_nl)] #![feature(generic_const_exprs)] +#![feature(int_roundings)] #![feature(is_sorted)] #![feature(linkage)] #![feature(panic_info_message)] @@ -182,7 +183,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); test_main(); diff --git a/18_backtrace/kernel/src/main.rs b/18_backtrace/kernel/src/main.rs index 928f12c2..9aeb4438 100644 --- a/18_backtrace/kernel/src/main.rs +++ b/18_backtrace/kernel/src/main.rs @@ -28,7 +28,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); // Instantiate and init all device drivers. if let Err(x) = bsp::driver::driver_manager().instantiate_drivers() { diff --git a/18_backtrace/kernel/src/memory.rs b/18_backtrace/kernel/src/memory.rs index 34c34429..840db396 100644 --- a/18_backtrace/kernel/src/memory.rs +++ b/18_backtrace/kernel/src/memory.rs @@ -160,6 +160,11 @@ impl fmt::Display for Address { } } +/// Initialize the memory subsystem. +pub fn init() { + mmu::kernel_init_mmio_va_allocator(); +} + //-------------------------------------------------------------------------------------------------- // Testing //-------------------------------------------------------------------------------------------------- diff --git a/18_backtrace/kernel/src/memory/mmu.rs b/18_backtrace/kernel/src/memory/mmu.rs index 8806a993..7f02dad9 100644 --- a/18_backtrace/kernel/src/memory/mmu.rs +++ b/18_backtrace/kernel/src/memory/mmu.rs @@ -82,14 +82,6 @@ use interface::MMU; use synchronization::interface::ReadWriteEx; use translation_table::interface::TranslationTable; -/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's -/// MMIO VA allocator with it. -fn kernel_init_mmio_va_allocator() { - let region = bsp::memory::mmu::virt_mmio_remap_region(); - - page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.initialize(region)); -} - /// Map a region in the kernel's translation tables. /// /// No input checks done, input is passed through to the architectural implementation. @@ -169,6 +161,14 @@ impl AddressSpace { } } +/// Query the BSP for the reserved virtual addresses for MMIO remapping and initialize the kernel's +/// MMIO VA allocator with it. +pub fn kernel_init_mmio_va_allocator() { + let region = bsp::memory::mmu::virt_mmio_remap_region(); + + page_alloc::kernel_mmio_va_allocator().lock(|allocator| allocator.init(region)); +} + /// Add an entry to the mapping info record. pub fn kernel_add_mapping_record( name: &'static str, @@ -247,6 +247,11 @@ pub fn try_kernel_page_attributes( .read(|tables| tables.try_page_attributes(virt_page_addr)) } +/// Human-readable print of all recorded kernel mappings. +pub fn kernel_print_mappings() { + mapping_record::kernel_print() +} + /// Enable the MMU and data + instruction caching. /// /// # Safety @@ -258,13 +263,3 @@ pub unsafe fn enable_mmu_and_caching( ) -> Result<(), MMUEnableError> { arch_mmu::mmu().enable_mmu_and_caching(phys_tables_base_addr) } - -/// Finish initialization of the MMU subsystem. -pub fn post_enable_init() { - kernel_init_mmio_va_allocator(); -} - -/// Human-readable print of all recorded kernel mappings. -pub fn kernel_print_mappings() { - mapping_record::kernel_print() -} diff --git a/18_backtrace/kernel/src/memory/mmu/mapping_record.rs b/18_backtrace/kernel/src/memory/mmu/mapping_record.rs index 7d3a6c60..5bc32445 100644 --- a/18_backtrace/kernel/src/memory/mmu/mapping_record.rs +++ b/18_backtrace/kernel/src/memory/mmu/mapping_record.rs @@ -8,7 +8,7 @@ use super::{ AccessPermissions, Address, AttributeFields, MMIODescriptor, MemAttributes, MemoryRegion, Physical, Virtual, }; -use crate::{bsp, info, synchronization, synchronization::InitStateLock, warn}; +use crate::{bsp, common, info, synchronization, synchronization::InitStateLock, warn}; //-------------------------------------------------------------------------------------------------- // Private Definitions @@ -141,9 +141,6 @@ impl MappingRecord { } pub fn print(&self) { - const KIB_RSHIFT: u32 = 10; // log2(1024). - const MIB_RSHIFT: u32 = 20; // log2(1024 * 1024). - info!(" -------------------------------------------------------------------------------------------------------------------------------------------"); info!( " {:^44} {:^30} {:^7} {:^9} {:^35}", @@ -158,13 +155,7 @@ impl MappingRecord { let phys_start = i.phys_start_addr; let phys_end_inclusive = phys_start + (size - 1); - let (size, unit) = if (size >> MIB_RSHIFT) > 0 { - (size >> MIB_RSHIFT, "MiB") - } else if (size >> KIB_RSHIFT) > 0 { - (size >> KIB_RSHIFT, "KiB") - } else { - (size, "Byte") - }; + let (size, unit) = common::size_human_readable_ceil(size); let attr = match i.attribute_fields.mem_attributes { MemAttributes::CacheableDRAM => "C", @@ -183,8 +174,7 @@ impl MappingRecord { }; info!( - " {}..{} --> {}..{} | \ - {: >3} {} | {: <3} {} {: <2} | {}", + " {}..{} --> {}..{} | {:>3} {} | {:<3} {} {:<2} | {}", virt_start, virt_end_inclusive, phys_start, diff --git a/18_backtrace/kernel/src/memory/mmu/page_alloc.rs b/18_backtrace/kernel/src/memory/mmu/page_alloc.rs index b4c4232c..347fcd34 100644 --- a/18_backtrace/kernel/src/memory/mmu/page_alloc.rs +++ b/18_backtrace/kernel/src/memory/mmu/page_alloc.rs @@ -44,7 +44,7 @@ impl PageAllocator { } /// Initialize the allocator. - pub fn initialize(&mut self, pool: MemoryRegion) { + pub fn init(&mut self, pool: MemoryRegion) { if self.pool.is_some() { warn!("Already initialized"); return; diff --git a/18_backtrace/kernel/tests/00_console_sanity.rs b/18_backtrace/kernel/tests/00_console_sanity.rs index f2a1f3ed..305510ce 100644 --- a/18_backtrace/kernel/tests/00_console_sanity.rs +++ b/18_backtrace/kernel/tests/00_console_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Handshake diff --git a/18_backtrace/kernel/tests/01_timer_sanity.rs b/18_backtrace/kernel/tests/01_timer_sanity.rs index caeca3cd..d5d76a5c 100644 --- a/18_backtrace/kernel/tests/01_timer_sanity.rs +++ b/18_backtrace/kernel/tests/01_timer_sanity.rs @@ -19,7 +19,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. diff --git a/18_backtrace/kernel/tests/02_exception_sync_page_fault.rs b/18_backtrace/kernel/tests/02_exception_sync_page_fault.rs index 33463e0a..a6d15b69 100644 --- a/18_backtrace/kernel/tests/02_exception_sync_page_fault.rs +++ b/18_backtrace/kernel/tests/02_exception_sync_page_fault.rs @@ -24,7 +24,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/18_backtrace/kernel/tests/03_exception_restore_sanity.rs b/18_backtrace/kernel/tests/03_exception_restore_sanity.rs index a521a871..47dd2714 100644 --- a/18_backtrace/kernel/tests/03_exception_restore_sanity.rs +++ b/18_backtrace/kernel/tests/03_exception_restore_sanity.rs @@ -33,7 +33,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); // This line will be printed as the test header. diff --git a/18_backtrace/kernel/tests/04_exception_irq_sanity.rs b/18_backtrace/kernel/tests/04_exception_irq_sanity.rs index cd2d29d6..7b9628d5 100644 --- a/18_backtrace/kernel/tests/04_exception_irq_sanity.rs +++ b/18_backtrace/kernel/tests/04_exception_irq_sanity.rs @@ -17,7 +17,7 @@ use test_macros::kernel_test; unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); exception::handling_init(); diff --git a/18_backtrace/kernel/tests/05_backtrace_sanity.rs b/18_backtrace/kernel/tests/05_backtrace_sanity.rs index 4475fafd..ea425f68 100644 --- a/18_backtrace/kernel/tests/05_backtrace_sanity.rs +++ b/18_backtrace/kernel/tests/05_backtrace_sanity.rs @@ -23,7 +23,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); nested(); diff --git a/18_backtrace/kernel/tests/06_backtrace_invalid_frame.rs b/18_backtrace/kernel/tests/06_backtrace_invalid_frame.rs index 74dad8d8..8769c7b6 100644 --- a/18_backtrace/kernel/tests/06_backtrace_invalid_frame.rs +++ b/18_backtrace/kernel/tests/06_backtrace_invalid_frame.rs @@ -25,7 +25,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); nested(); diff --git a/18_backtrace/kernel/tests/07_backtrace_invalid_link.rs b/18_backtrace/kernel/tests/07_backtrace_invalid_link.rs index ba6c9f57..28f3cdda 100644 --- a/18_backtrace/kernel/tests/07_backtrace_invalid_link.rs +++ b/18_backtrace/kernel/tests/07_backtrace_invalid_link.rs @@ -30,7 +30,7 @@ unsafe fn kernel_init() -> ! { use driver::interface::DriverManager; exception::handling_init(); - memory::mmu::post_enable_init(); + memory::init(); bsp::driver::driver_manager().qemu_bring_up_console(); nested_1(); diff --git a/18_backtrace/tools/translation_table_tool/bsp.rb b/18_backtrace/tools/translation_table_tool/bsp.rb index 536a2f21..dbab5ab6 100644 --- a/18_backtrace/tools/translation_table_tool/bsp.rb +++ b/18_backtrace/tools/translation_table_tool/bsp.rb @@ -45,6 +45,10 @@ class RaspberryPi raise end - x.scan(/\d+/).join.to_i(16) + # Extract the hex literal with underscores like 0x0123_abcd. + x = x.scan(/0x[\h_]*/)[0] + + # Further remove x and _ and convert to int. + x.scan(/\h+/).join.to_i(16) end end diff --git a/18_backtrace/tools/translation_table_tool/generic.rb b/18_backtrace/tools/translation_table_tool/generic.rb index 13df0658..eee8ccda 100644 --- a/18_backtrace/tools/translation_table_tool/generic.rb +++ b/18_backtrace/tools/translation_table_tool/generic.rb @@ -109,13 +109,23 @@ class MappingDescriptor @attributes = attributes end + def size_human_readable(size) + if size >= (1024 * 1024) + "#{(size / (1024 * 1024)).to_s.rjust(3)} MiB" + elsif size >= 1024 + "#{(size / 1024).to_s.rjust(3)} KiB" + else + raise + end + end + def to_s name = @name.ljust(self.class.max_section_name_length) virt_start = @virt_region.first.to_hex_underscore(with_leading_zeros: true) phys_start = @phys_region.first.to_hex_underscore(with_leading_zeros: true) - size = ((@virt_region.size * 65_536) / 1024).to_s.rjust(3) + size = size_human_readable(@virt_region.size * 65_536) - "#{name} | #{virt_start} | #{phys_start} | #{size} KiB | #{@attributes}" + "#{name} | #{virt_start} | #{phys_start} | #{size} | #{@attributes}" end def self.print_divider