From 644426d80630ab0e4710aa7c326ef8118893d6fc Mon Sep 17 00:00:00 2001 From: Berkus Decker Date: Mon, 22 Mar 2021 01:36:01 +0200 Subject: [PATCH] wip mmu --- README.md | 4 + .../arch/aarch64/memory/mmu-experimental.rs | 88 +++++++------------ nucleus/src/arch/aarch64/memory/mmu.rs | 60 ++++++++++++- 3 files changed, 93 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 95290af..900856e 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,10 @@ Individual files contain the following tag instead of the full license text. This enables machine processing of license information based on the SPDX License Identifiers that are here available: http://spdx.org/licenses/ +@todo http://copyfree.org/support/community +-- copyfree +-- no CoC approach of that community + ---- For more information please re-read. diff --git a/nucleus/src/arch/aarch64/memory/mmu-experimental.rs b/nucleus/src/arch/aarch64/memory/mmu-experimental.rs index a865df6..463cc99 100644 --- a/nucleus/src/arch/aarch64/memory/mmu-experimental.rs +++ b/nucleus/src/arch/aarch64/memory/mmu-experimental.rs @@ -216,17 +216,17 @@ impl From for u64 { // So, first we init the dtb, parse mem-regions from there, then init boot_info page and start mmu, // this part will be inited in mmu::init(): -// @todo do NOT keep these statically, always allocate from available bump memory -static mut LVL2_TABLE: Table = Table:: { - entries: [0; NUM_ENTRIES_4KIB as usize], - level: PhantomData, -}; - -// @todo do NOT keep these statically, always allocate from available bump memory -static mut LVL3_TABLE: Table = Table:: { - entries: [0; NUM_ENTRIES_4KIB as usize], - level: PhantomData, -}; +// // @todo do NOT keep these statically, always allocate from available bump memory +// static mut LVL2_TABLE: Table = Table:: { +// entries: [0; NUM_ENTRIES_4KIB as usize], +// level: PhantomData, +// }; +// +// // @todo do NOT keep these statically, always allocate from available bump memory +// static mut LVL3_TABLE: Table = Table:: { +// entries: [0; NUM_ENTRIES_4KIB as usize], +// level: PhantomData, +// }; trait BaseAddr { fn base_addr_u64(&self) -> u64; @@ -254,10 +254,27 @@ pub unsafe fn init() -> Result<(), &'static str> { // Prepare the memory attribute indirection register. mair::set_up(); + // should receive in args an obtained memory map from DT + let memory_map = Regions { + start: 0x1000, + size: 0x10000, + }; + + // bump-allocate page tables for entire memory + // also allocate phys memory to kernel space! + // + // separate regions - regular memory, device mmaps, + // initial thread maps ALL the memory?? + // instead + // init thread may map only necessary mem + // boot time only map kernel physmem space, and currently loaded kernel data + // PROBABLY only kernel mapping TTBR1 is needed, the rest is not very useful? + // take over protected memory space though anyway. + // Point the first 2 MiB of virtual addresses to the follow-up LVL3 // page-table. - LVL2_TABLE.entries[0] = - PageTableEntry::new_table_descriptor(LVL3_TABLE.entries.base_addr_usize())?.into(); + // LVL2_TABLE.entries[0] = + // PageTableEntry::new_table_descriptor(LVL3_TABLE.entries.base_addr_usize())?.into(); // Fill the rest of the LVL2 (2 MiB) entries as block descriptors. // @@ -296,51 +313,6 @@ pub unsafe fn init() -> Result<(), &'static str> { *entry = page_desc.into(); } - - // Point to the LVL2 table base address in TTBR0. - TTBR0_EL1.set_baddr(LVL2_TABLE.entries.base_addr_u64()); // User (lo-)space addresses - - // TTBR1_EL1.set_baddr(LVL2_TABLE.entries.base_addr_u64()); // Kernel (hi-)space addresses - - // Configure various settings of stage 1 of the EL1 translation regime. - let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); - TCR_EL1.write( - TCR_EL1::TBI0::Ignored // @todo TBI1 also set to Ignored?? - + TCR_EL1::IPS.val(ips) // Intermediate Physical Address Size - // ttbr0 user memory addresses - + TCR_EL1::TG0::KiB_4 // 4 KiB granule - + TCR_EL1::SH0::Inner - + TCR_EL1::ORGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable - + TCR_EL1::IRGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable - + TCR_EL1::EPD0::EnableTTBR0Walks - + TCR_EL1::T0SZ.val(34) // ARMv8ARM Table D5-11 minimum TxSZ for starting table level 2 - // ttbr1 kernel memory addresses - + TCR_EL1::TG1::KiB_4 // 4 KiB granule - + TCR_EL1::SH1::Inner - + TCR_EL1::ORGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable - + TCR_EL1::IRGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable - + TCR_EL1::EPD1::EnableTTBR1Walks - + TCR_EL1::T1SZ.val(34), // ARMv8ARM Table D5-11 minimum TxSZ for starting table level 2 - ); - - // Switch the MMU on. - // - // First, force all previous changes to be seen before the MMU is enabled. - barrier::isb(barrier::SY); - - // use cortex_a::regs::RegisterReadWrite; - // 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 - /* - * Invalidate the local I-cache so that any instructions fetched - * speculatively from the PoC are discarded, since they may have - * been dynamically patched at the PoU. - */ - barrier::isb(barrier::SY); - - Ok(()) } // AArch64: diff --git a/nucleus/src/arch/aarch64/memory/mmu.rs b/nucleus/src/arch/aarch64/memory/mmu.rs index 96fd488..d4c6cba 100644 --- a/nucleus/src/arch/aarch64/memory/mmu.rs +++ b/nucleus/src/arch/aarch64/memory/mmu.rs @@ -12,10 +12,10 @@ #![allow(dead_code)] -use crate::memory::PageSize; use { crate::memory::{ page_size::{Size1GiB, Size2MiB, Size4KiB}, + PageSize, //virt_page::Page, PhysAddr, PhysFrame, @@ -26,10 +26,68 @@ use { ops::{Index, IndexMut}, ptr::Unique, }, + cortex_a::barrier, register::register_bitfields, snafu::Snafu, }; +#[derive(Debug, Snafu)] +enum MmuError {} + +pub fn init() -> Result<(), MmuError> { + // Prepare the memory attribute indirection register. + mair::set_up(); + + // Point to the LVL2 table base address in TTBR0. + TTBR0_EL1.set_baddr(LVL2_TABLE.entries.base_addr_u64()); // User (lo-)space addresses + + // TTBR1_EL1.set_baddr(LVL2_TABLE.entries.base_addr_u64()); // Kernel (hi-)space addresses + + // Configure various settings of stage 1 of the EL1 translation regime. + let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); + TCR_EL1.write( + TCR_EL1::TBI0::Ignored // @todo TBI1 also set to Ignored?? + + TCR_EL1::IPS.val(ips) // Intermediate Physical Address Size + // ttbr0 user memory addresses + + TCR_EL1::TG0::KiB_4 // 4 KiB granule + + TCR_EL1::SH0::Inner + + TCR_EL1::ORGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::IRGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::EPD0::EnableTTBR0Walks + + TCR_EL1::T0SZ.val(34) // ARMv8ARM Table D5-11 minimum TxSZ for starting table level 2 + // ttbr1 kernel memory addresses + + TCR_EL1::TG1::KiB_4 // 4 KiB granule + + TCR_EL1::SH1::Inner + + TCR_EL1::ORGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::IRGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::EPD1::EnableTTBR1Walks + + TCR_EL1::T1SZ.val(34), // ARMv8ARM Table D5-11 minimum TxSZ for starting table level 2 + ); + + // Switch the MMU on. + // + // First, force all previous changes to be seen before the MMU is enabled. + unsafe { + barrier::isb(barrier::SY); + } + + // use cortex_a::regs::RegisterReadWrite; + // 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 + /* + * Invalidate the local I-cache so that any instructions fetched + * speculatively from the PoC are discarded, since they may have + * been dynamically patched at the PoU. + */ + unsafe { + barrier::isb(barrier::SY); + } + + Ok(()) +} + /* * With 4k page granule, a virtual address is split into 4 lookup parts * spanning 9 bits each: