Housekeeping

pull/37/head
Andre Richter 5 years ago
parent 8c2b18e8ce
commit b2219ca520
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -55,7 +55,7 @@ make qemu
diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/src/arch/aarch64/sync.rs diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/src/arch/aarch64/sync.rs
--- 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs --- 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs
+++ 05_safe_globals/src/arch/aarch64/sync.rs +++ 05_safe_globals/src/arch/aarch64/sync.rs
@@ -0,0 +1,44 @@ @@ -0,0 +1,52 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -65,6 +65,10 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/
+use crate::interface; +use crate::interface;
+use core::cell::UnsafeCell; +use core::cell::UnsafeCell;
+ +
+//--------------------------------------------------------------------------------------------------
+// Arch-public
+//--------------------------------------------------------------------------------------------------
+
+/// A pseudo-lock for teaching purposes. +/// A pseudo-lock for teaching purposes.
+/// +///
+/// Used to introduce [interior mutability]. +/// Used to introduce [interior mutability].
@ -91,6 +95,10 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/
+ } + }
+} +}
+ +
+//--------------------------------------------------------------------------------------------------
+// OS interface implementations
+//--------------------------------------------------------------------------------------------------
+
+impl<T> interface::sync::Mutex for &NullLock<T> { +impl<T> interface::sync::Mutex for &NullLock<T> {
+ type Data = T; + type Data = T;
+ +

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

Binary file not shown.

Binary file not shown.

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

Binary file not shown.

Binary file not shown.

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

@ -100,7 +100,7 @@ diff -uNr 07_uart_chainloader/Makefile 08_timestamps/Makefile
diff -uNr 07_uart_chainloader/src/arch/aarch64/time.rs 08_timestamps/src/arch/aarch64/time.rs diff -uNr 07_uart_chainloader/src/arch/aarch64/time.rs 08_timestamps/src/arch/aarch64/time.rs
--- 07_uart_chainloader/src/arch/aarch64/time.rs --- 07_uart_chainloader/src/arch/aarch64/time.rs
+++ 08_timestamps/src/arch/aarch64/time.rs +++ 08_timestamps/src/arch/aarch64/time.rs
@@ -0,0 +1,77 @@ @@ -0,0 +1,85 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -113,8 +113,16 @@ diff -uNr 07_uart_chainloader/src/arch/aarch64/time.rs 08_timestamps/src/arch/aa
+ +
+const NS_PER_S: u64 = 1_000_000_000; +const NS_PER_S: u64 = 1_000_000_000;
+ +
+//--------------------------------------------------------------------------------------------------
+// Arch-public
+//--------------------------------------------------------------------------------------------------
+
+pub struct Timer; +pub struct Timer;
+ +
+//--------------------------------------------------------------------------------------------------
+// OS interface implementations
+//--------------------------------------------------------------------------------------------------
+
+impl interface::time::Timer for Timer { +impl interface::time::Timer for Timer {
+ fn resolution(&self) -> Duration { + fn resolution(&self) -> Duration {
+ Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64)) + Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))

Binary file not shown.

Binary file not shown.

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

@ -10,8 +10,16 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000; const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub struct Timer; pub struct Timer;
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl interface::time::Timer for Timer { impl interface::time::Timer for Timer {
fn resolution(&self) -> Duration { fn resolution(&self) -> Duration {
Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64)) Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))

Binary file not shown.

Binary file not shown.

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

@ -10,8 +10,16 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000; const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub struct Timer; pub struct Timer;
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl interface::time::Timer for Timer { impl interface::time::Timer for Timer {
fn resolution(&self) -> Duration { fn resolution(&self) -> Duration {
Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64)) Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))

@ -213,7 +213,7 @@ make chainbot
diff -uNr 09_hw_debug_JTAG/src/arch/aarch64/exception.rs 10_privilege_level/src/arch/aarch64/exception.rs diff -uNr 09_hw_debug_JTAG/src/arch/aarch64/exception.rs 10_privilege_level/src/arch/aarch64/exception.rs
--- 09_hw_debug_JTAG/src/arch/aarch64/exception.rs --- 09_hw_debug_JTAG/src/arch/aarch64/exception.rs
+++ 10_privilege_level/src/arch/aarch64/exception.rs +++ 10_privilege_level/src/arch/aarch64/exception.rs
@@ -0,0 +1,44 @@ @@ -0,0 +1,48 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -222,6 +222,10 @@ diff -uNr 09_hw_debug_JTAG/src/arch/aarch64/exception.rs 10_privilege_level/src/
+ +
+use cortex_a::regs::*; +use cortex_a::regs::*;
+ +
+//--------------------------------------------------------------------------------------------------
+// Arch-public
+//--------------------------------------------------------------------------------------------------
+
+pub trait DaifField { +pub trait DaifField {
+ fn daif_field() -> register::Field<u32, DAIF::Register>; + fn daif_field() -> register::Field<u32, DAIF::Register>;
+} +}
@ -339,7 +343,7 @@ diff -uNr 09_hw_debug_JTAG/src/arch/aarch64.rs 10_privilege_level/src/arch/aarch
+pub mod state { +pub mod state {
+ use cortex_a::regs::*; + use cortex_a::regs::*;
+ +
+ /// The current privilege level. + /// The processing element's current privilege level.
+ pub fn current_privilege_level() -> &'static str { + pub fn current_privilege_level() -> &'static str {
+ let el = CurrentEL.read_as_enum(CurrentEL::EL); + let el = CurrentEL.read_as_enum(CurrentEL::EL);
+ match el { + match el {

Binary file not shown.

Binary file not shown.

@ -108,7 +108,7 @@ pub fn wait_forever() -> ! {
pub mod state { pub mod state {
use cortex_a::regs::*; use cortex_a::regs::*;
/// The current privilege level. /// The processing element's current privilege level.
pub fn current_privilege_level() -> &'static str { pub fn current_privilege_level() -> &'static str {
let el = CurrentEL.read_as_enum(CurrentEL::EL); let el = CurrentEL.read_as_enum(CurrentEL::EL);
match el { match el {

@ -6,6 +6,10 @@
use cortex_a::regs::*; use cortex_a::regs::*;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub trait DaifField { pub trait DaifField {
fn daif_field() -> register::Field<u32, DAIF::Register>; fn daif_field() -> register::Field<u32, DAIF::Register>;
} }

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

@ -10,8 +10,16 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000; const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub struct Timer; pub struct Timer;
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl interface::time::Timer for Timer { impl interface::time::Timer for Timer {
fn resolution(&self) -> Duration { fn resolution(&self) -> Duration {
Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64)) Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))

@ -262,10 +262,23 @@ make chainbot
## Diff to previous ## Diff to previous
```diff ```diff
diff -uNr 10_privilege_level/Makefile 11_virtual_memory/Makefile
--- 10_privilege_level/Makefile
+++ 11_virtual_memory/Makefile
@@ -17,7 +17,7 @@
OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi3.cfg
JTAG_BOOT_IMAGE = jtag_boot_rpi3.img
LINKER_FILE = src/bsp/rpi/link.ld
- RUSTC_MISC_ARGS = -C target-cpu=cortex-a53
+ RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 -C llvm-args=-ffixed-x18
else ifeq ($(BSP),rpi4)
TARGET = aarch64-unknown-none-softfloat
OUTPUT = kernel8.img
diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/aarch64/mmu.rs diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/aarch64/mmu.rs
--- 10_privilege_level/src/arch/aarch64/mmu.rs --- 10_privilege_level/src/arch/aarch64/mmu.rs
+++ 11_virtual_memory/src/arch/aarch64/mmu.rs +++ 11_virtual_memory/src/arch/aarch64/mmu.rs
@@ -0,0 +1,309 @@ @@ -0,0 +1,316 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -275,7 +288,7 @@ diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/
+//! Static page tables, compiled on boot; Everything 64 KiB granule. +//! Static page tables, compiled on boot; Everything 64 KiB granule.
+ +
+use crate::{ +use crate::{
+ bsp, + bsp, interface,
+ memory::{AccessPermissions, AttributeFields, MemAttributes}, + memory::{AccessPermissions, AttributeFields, MemAttributes},
+}; +};
+use core::convert; +use core::convert;
@ -511,10 +524,7 @@ diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/
+ let virt_addr = (l2_nr << FIVETWELVE_MIB_SHIFT) + (l3_nr << SIXTYFOUR_KIB_SHIFT); + let virt_addr = (l2_nr << FIVETWELVE_MIB_SHIFT) + (l3_nr << SIXTYFOUR_KIB_SHIFT);
+ +
+ let (output_addr, attribute_fields) = + let (output_addr, attribute_fields) =
+ match bsp::virt_mem_layout().get_virt_addr_properties(virt_addr) { + bsp::virt_mem_layout().get_virt_addr_properties(virt_addr)?;
+ Err(string) => return Err(string),
+ Ok((a, b)) => (a, b),
+ };
+ +
+ *l3_entry = PageDescriptor::new(output_addr, attribute_fields).into(); + *l3_entry = PageDescriptor::new(output_addr, attribute_fields).into();
+ } + }
@ -538,42 +548,52 @@ diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/
+ ); + );
+} +}
+ +
+/// Compile the page tables from the `BSP`-supplied `virt_mem_layout()`. +//--------------------------------------------------------------------------------------------------
+/// +// Arch-public
+/// # Safety +//--------------------------------------------------------------------------------------------------
+///
+/// - User must ensure that the hardware supports the paremeters being set here.
+pub unsafe fn init() -> Result<(), &'static str> {
+ // Fail early if translation granule is not supported. Both RPis support it, though.
+ if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) {
+ return Err("64 KiB translation granule not supported");
+ }
+ +
+ // Prepare the memory attribute indirection register. +pub struct MMU;
+ set_up_mair();
+ +
+ // Populate page tables. +//--------------------------------------------------------------------------------------------------
+ if let Err(string) = populate_pt_entries() { +// OS interface implementations
+ return Err(string); +//--------------------------------------------------------------------------------------------------
+ }
+ +
+ // Set the "Translation Table Base Register". +impl interface::mm::MMU for MMU {
+ TTBR0_EL1.set_baddr(TABLES.lvl2.base_addr_u64()); + /// Compile the page tables from the `BSP`-supplied `virt_mem_layout()`.
+ ///
+ /// # Safety
+ ///
+ /// - User must ensure that the hardware supports the paremeters being set here.
+ unsafe fn init(&self) -> Result<(), &'static str> {
+ // Fail early if translation granule is not supported. Both RPis support it, though.
+ if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) {
+ return Err("64 KiB translation granule not supported");
+ }
+ +
+ configure_translation_control(); + // Prepare the memory attribute indirection register.
+ set_up_mair();
+ +
+ // Switch the MMU on. + // Populate page tables.
+ // + populate_pt_entries()?;
+ // First, force all previous changes to be seen before the MMU is enabled.
+ barrier::isb(barrier::SY);
+ +
+ // Enable the MMU and turn on data and instruction caching. + // Set the "Translation Table Base Register".
+ SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); + TTBR0_EL1.set_baddr(TABLES.lvl2.base_addr_u64());
+ +
+ // Force MMU init to complete before next instruction + configure_translation_control();
+ barrier::isb(barrier::SY);
+ +
+ Ok(()) + // Switch the MMU on.
+ //
+ // First, force all previous changes to be seen before the MMU is enabled.
+ barrier::isb(barrier::SY);
+
+ // Enable the MMU and turn on data and instruction caching.
+ SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable);
+
+ // Force MMU init to complete before next instruction
+ barrier::isb(barrier::SY);
+
+ Ok(())
+ }
+} +}
diff -uNr 10_privilege_level/src/arch/aarch64.rs 11_virtual_memory/src/arch/aarch64.rs diff -uNr 10_privilege_level/src/arch/aarch64.rs 11_virtual_memory/src/arch/aarch64.rs
@ -583,10 +603,27 @@ diff -uNr 10_privilege_level/src/arch/aarch64.rs 11_virtual_memory/src/arch/aarc
//! AArch64. //! AArch64.
mod exception; mod exception;
+pub mod mmu; +mod mmu;
pub mod sync; pub mod sync;
mod time; mod time;
@@ -77,6 +78,7 @@
//--------------------------------------------------------------------------------------------------
static TIMER: time::Timer = time::Timer;
+static MMU: mmu::MMU = mmu::MMU;
//--------------------------------------------------------------------------------------------------
// Implementation of the kernel's architecture abstraction code
@@ -136,3 +138,8 @@
println!(" FIQ: {}", to_mask_str(exception::is_masked::<FIQ>()));
}
}
+
+/// Return a reference to an `interface::mm::MMU` implementation.
+pub fn mmu() -> &'static impl interface::mm::MMU {
+ &MMU
+}
diff -uNr 10_privilege_level/src/bsp/rpi/link.ld 11_virtual_memory/src/bsp/rpi/link.ld diff -uNr 10_privilege_level/src/bsp/rpi/link.ld 11_virtual_memory/src/bsp/rpi/link.ld
--- 10_privilege_level/src/bsp/rpi/link.ld --- 10_privilege_level/src/bsp/rpi/link.ld
@ -637,7 +674,7 @@ diff -uNr 10_privilege_level/src/bsp/rpi/memory_map.rs 11_virtual_memory/src/bsp
diff -uNr 10_privilege_level/src/bsp/rpi/virt_mem_layout.rs 11_virtual_memory/src/bsp/rpi/virt_mem_layout.rs diff -uNr 10_privilege_level/src/bsp/rpi/virt_mem_layout.rs 11_virtual_memory/src/bsp/rpi/virt_mem_layout.rs
--- 10_privilege_level/src/bsp/rpi/virt_mem_layout.rs --- 10_privilege_level/src/bsp/rpi/virt_mem_layout.rs
+++ 11_virtual_memory/src/bsp/rpi/virt_mem_layout.rs +++ 11_virtual_memory/src/bsp/rpi/virt_mem_layout.rs
@@ -0,0 +1,78 @@ @@ -0,0 +1,82 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -651,6 +688,10 @@ diff -uNr 10_privilege_level/src/bsp/rpi/virt_mem_layout.rs 11_virtual_memory/sr
+use crate::memory::*; +use crate::memory::*;
+use core::ops::RangeInclusive; +use core::ops::RangeInclusive;
+ +
+//--------------------------------------------------------------------------------------------------
+// BSP-public
+//--------------------------------------------------------------------------------------------------
+
+pub const NUM_MEM_RANGES: usize = 3; +pub const NUM_MEM_RANGES: usize = 3;
+ +
+pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new( +pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(
@ -760,6 +801,22 @@ diff -uNr 10_privilege_level/src/bsp.rs 11_virtual_memory/src/bsp.rs
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))] #[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
mod rpi; mod rpi;
diff -uNr 10_privilege_level/src/interface.rs 11_virtual_memory/src/interface.rs
--- 10_privilege_level/src/interface.rs
+++ 11_virtual_memory/src/interface.rs
@@ -127,3 +127,11 @@
fn spin_for(&self, duration: Duration);
}
}
+
+/// Memory Management interfaces.
+pub mod mm {
+ pub trait MMU {
+ /// Called by the kernel early during init.
+ unsafe fn init(&self) -> Result<(), &'static str>;
+ }
+}
diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
--- 10_privilege_level/src/main.rs --- 10_privilege_level/src/main.rs
+++ 11_virtual_memory/src/main.rs +++ 11_virtual_memory/src/main.rs
@ -780,7 +837,7 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
mod panic_wait; mod panic_wait;
mod print; mod print;
@@ -46,8 +49,16 @@ @@ -46,8 +49,18 @@
/// # Safety /// # Safety
/// ///
/// - Only a single core must be active and running this function. /// - Only a single core must be active and running this function.
@ -791,14 +848,16 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
+/// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on +/// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on
+/// the RPi SoCs. +/// the RPi SoCs.
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
+ if let Err(string) = arch::mmu::init() { + use interface::mm::MMU;
+
+ if let Err(string) = arch::mmu().init() {
+ panic!("MMU: {}", string); + panic!("MMU: {}", string);
+ } + }
+ +
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { if let Err(()) = i.init() {
panic!("Error loading driver: {}", i.compatible()) panic!("Error loading driver: {}", i.compatible())
@@ -67,6 +78,9 @@ @@ -67,6 +80,9 @@
println!("Booting on: {}", bsp::board_name()); println!("Booting on: {}", bsp::board_name());
@ -808,7 +867,7 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
println!( println!(
"Current privilege level: {}", "Current privilege level: {}",
arch::state::current_privilege_level() arch::state::current_privilege_level()
@@ -87,6 +101,13 @@ @@ -87,6 +103,13 @@
println!("Timer test, spinning for 1 second"); println!("Timer test, spinning for 1 second");
arch::timer().spin_for(Duration::from_secs(1)); arch::timer().spin_for(Duration::from_secs(1));

Binary file not shown.

Binary file not shown.

@ -5,7 +5,7 @@
//! AArch64. //! AArch64.
mod exception; mod exception;
pub mod mmu; mod mmu;
pub mod sync; pub mod sync;
mod time; mod time;
@ -78,6 +78,7 @@ unsafe fn el2_to_el1_transition() -> ! {
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
static TIMER: time::Timer = time::Timer; static TIMER: time::Timer = time::Timer;
static MMU: mmu::MMU = mmu::MMU;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Implementation of the kernel's architecture abstraction code // Implementation of the kernel's architecture abstraction code
@ -109,7 +110,7 @@ pub fn wait_forever() -> ! {
pub mod state { pub mod state {
use cortex_a::regs::*; use cortex_a::regs::*;
/// The current privilege level. /// The processing element's current privilege level.
pub fn current_privilege_level() -> &'static str { pub fn current_privilege_level() -> &'static str {
let el = CurrentEL.read_as_enum(CurrentEL::EL); let el = CurrentEL.read_as_enum(CurrentEL::EL);
match el { match el {
@ -137,3 +138,8 @@ pub mod state {
println!(" FIQ: {}", to_mask_str(exception::is_masked::<FIQ>())); println!(" FIQ: {}", to_mask_str(exception::is_masked::<FIQ>()));
} }
} }
/// Return a reference to an `interface::mm::MMU` implementation.
pub fn mmu() -> &'static impl interface::mm::MMU {
&MMU
}

@ -6,6 +6,10 @@
use cortex_a::regs::*; use cortex_a::regs::*;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub trait DaifField { pub trait DaifField {
fn daif_field() -> register::Field<u32, DAIF::Register>; fn daif_field() -> register::Field<u32, DAIF::Register>;
} }

@ -7,7 +7,7 @@
//! Static page tables, compiled on boot; Everything 64 KiB granule. //! Static page tables, compiled on boot; Everything 64 KiB granule.
use crate::{ use crate::{
bsp, bsp, interface,
memory::{AccessPermissions, AttributeFields, MemAttributes}, memory::{AccessPermissions, AttributeFields, MemAttributes},
}; };
use core::convert; use core::convert;
@ -243,10 +243,7 @@ unsafe fn populate_pt_entries() -> Result<(), &'static str> {
let virt_addr = (l2_nr << FIVETWELVE_MIB_SHIFT) + (l3_nr << SIXTYFOUR_KIB_SHIFT); let virt_addr = (l2_nr << FIVETWELVE_MIB_SHIFT) + (l3_nr << SIXTYFOUR_KIB_SHIFT);
let (output_addr, attribute_fields) = let (output_addr, attribute_fields) =
match bsp::virt_mem_layout().get_virt_addr_properties(virt_addr) { bsp::virt_mem_layout().get_virt_addr_properties(virt_addr)?;
Err(string) => return Err(string),
Ok((a, b)) => (a, b),
};
*l3_entry = PageDescriptor::new(output_addr, attribute_fields).into(); *l3_entry = PageDescriptor::new(output_addr, attribute_fields).into();
} }
@ -270,40 +267,50 @@ fn configure_translation_control() {
); );
} }
/// Compile the page tables from the `BSP`-supplied `virt_mem_layout()`. //--------------------------------------------------------------------------------------------------
/// // Arch-public
/// # Safety //--------------------------------------------------------------------------------------------------
///
/// - User must ensure that the hardware supports the paremeters being set here. pub struct MMU;
pub unsafe fn init() -> Result<(), &'static str> {
// Fail early if translation granule is not supported. Both RPis support it, though. //--------------------------------------------------------------------------------------------------
if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) { // OS interface implementations
return Err("64 KiB translation granule not supported"); //--------------------------------------------------------------------------------------------------
}
impl interface::mm::MMU for MMU {
/// Compile the page tables from the `BSP`-supplied `virt_mem_layout()`.
///
/// # Safety
///
/// - User must ensure that the hardware supports the paremeters being set here.
unsafe fn init(&self) -> Result<(), &'static str> {
// Fail early if translation granule is not supported. Both RPis support it, though.
if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) {
return Err("64 KiB translation granule not supported");
}
// Prepare the memory attribute indirection register. // Prepare the memory attribute indirection register.
set_up_mair(); set_up_mair();
// Populate page tables. // Populate page tables.
if let Err(string) = populate_pt_entries() { populate_pt_entries()?;
return Err(string);
}
// Set the "Translation Table Base Register". // Set the "Translation Table Base Register".
TTBR0_EL1.set_baddr(TABLES.lvl2.base_addr_u64()); TTBR0_EL1.set_baddr(TABLES.lvl2.base_addr_u64());
configure_translation_control(); configure_translation_control();
// Switch the MMU on. // Switch the MMU on.
// //
// First, force all previous changes to be seen before the MMU is enabled. // First, force all previous changes to be seen before the MMU is enabled.
barrier::isb(barrier::SY); barrier::isb(barrier::SY);
// Enable the MMU and turn on data and instruction caching. // Enable the MMU and turn on data and instruction caching.
SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable);
// Force MMU init to complete before next instruction // Force MMU init to complete before next instruction
barrier::isb(barrier::SY); barrier::isb(barrier::SY);
Ok(()) Ok(())
}
} }

@ -7,6 +7,10 @@
use crate::interface; use crate::interface;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
/// A pseudo-lock for teaching purposes. /// A pseudo-lock for teaching purposes.
/// ///
/// Used to introduce [interior mutability]. /// Used to introduce [interior mutability].
@ -33,6 +37,10 @@ impl<T> NullLock<T> {
} }
} }
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl<T> interface::sync::Mutex for &NullLock<T> { impl<T> interface::sync::Mutex for &NullLock<T> {
type Data = T; type Data = T;

@ -10,8 +10,16 @@ use cortex_a::regs::*;
const NS_PER_S: u64 = 1_000_000_000; const NS_PER_S: u64 = 1_000_000_000;
//--------------------------------------------------------------------------------------------------
// Arch-public
//--------------------------------------------------------------------------------------------------
pub struct Timer; pub struct Timer;
//--------------------------------------------------------------------------------------------------
// OS interface implementations
//--------------------------------------------------------------------------------------------------
impl interface::time::Timer for Timer { impl interface::time::Timer for Timer {
fn resolution(&self) -> Duration { fn resolution(&self) -> Duration {
Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64)) Duration::from_nanos(NS_PER_S / (CNTFRQ_EL0.get() as u64))

@ -11,6 +11,10 @@ use super::memory_map;
use crate::memory::*; use crate::memory::*;
use core::ops::RangeInclusive; use core::ops::RangeInclusive;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
pub const NUM_MEM_RANGES: usize = 3; pub const NUM_MEM_RANGES: usize = 3;
pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new( pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout::new(

@ -127,3 +127,11 @@ pub mod time {
fn spin_for(&self, duration: Duration); fn spin_for(&self, duration: Duration);
} }
} }
/// Memory Management interfaces.
pub mod mm {
pub trait MMU {
/// Called by the kernel early during init.
unsafe fn init(&self) -> Result<(), &'static str>;
}
}

@ -55,7 +55,9 @@ mod print;
/// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on /// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on
/// the RPi SoCs. /// the RPi SoCs.
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
if let Err(string) = arch::mmu::init() { use interface::mm::MMU;
if let Err(string) = arch::mmu().init() {
panic!("MMU: {}", string); panic!("MMU: {}", string);
} }

Loading…
Cancel
Save