@@ -457,19 +457,23 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
457457 val.write(
458458 STAGE1_TABLE_DESCRIPTOR::NEXT_LEVEL_TABLE_ADDR_64KiB.val(shifted as u64)
459459 + STAGE1_TABLE_DESCRIPTOR::TYPE::Table
460- @@ -230,7 +229,10 @@
460+ @@ -230,10 +229,13 @@
461461 }
462462
463463 /// Create an instance.
464464- pub fn from_output_addr(phys_output_addr: usize, attribute_fields: &AttributeFields) -> Self {
465- + pub fn from_output_addr (
466- + phys_output_addr : *const Page<Physical>,
465+ + pub fn from_output_page (
466+ + phys_output_page : *const Page<Physical>,
467467+ attribute_fields: &AttributeFields,
468468+ ) -> Self {
469469 let val = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(0);
470470
471- let shifted = phys_output_addr as u64 >> Granule64KiB::SHIFT;
472- @@ -244,50 +246,193 @@
471+ - let shifted = phys_output_addr as u64 >> Granule64KiB::SHIFT;
472+ + let shifted = phys_output_page as u64 >> Granule64KiB::SHIFT;
473+ val.write(
474+ STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB.val(shifted)
475+ + STAGE1_PAGE_DESCRIPTOR::AF::True
476+ @@ -244,50 +246,201 @@
473477
474478 Self { value: val.get() }
475479 }
@@ -517,12 +521,6 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
517521- /// Iterates over all static translation table entries and fills them at once.
518522- ///
519523- /// # Safety
520- - ///
521- - /// - Modifies a `static mut`. Ensure it only happens from here.
522- - pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
523- - for (l2_nr, l2_entry) in self.lvl2.iter_mut().enumerate() {
524- - *l2_entry =
525- - TableDescriptor::from_next_lvl_table_addr(self.lvl3[l2_nr].phys_start_addr_usize());
526524+ /// The start address of the table's MMIO range.
527525+ #[inline(always)]
528526+ fn mmio_start_addr(&self) -> Address<Virtual> {
@@ -544,11 +542,11 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
544542+
545543+ /// Helper to calculate the lvl2 and lvl3 indices from an address.
546544+ #[inline(always)]
547- + fn lvl2_lvl3_index_from (
545+ + fn lvl2_lvl3_index_from_page (
548546+ &self,
549- + addr : *const Page<Virtual>,
547+ + virt_page : *const Page<Virtual>,
550548+ ) -> Result<(usize, usize), &'static str> {
551- + let addr = addr as usize;
549+ + let addr = virt_page as usize;
552550+ let lvl2_index = addr >> Granule512MiB::SHIFT;
553551+ let lvl3_index = (addr & Granule512MiB::MASK) >> Granule64KiB::SHIFT;
554552+
@@ -559,24 +557,42 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
559557+ Ok((lvl2_index, lvl3_index))
560558+ }
561559+
562- + /// Returns the PageDescriptor corresponding to the supplied Page.
560+ + /// Sets the PageDescriptor corresponding to the supplied page address.
561+ ///
562+ - /// - Modifies a `static mut`. Ensure it only happens from here.
563+ - pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
564+ - for (l2_nr, l2_entry) in self.lvl2.iter_mut().enumerate() {
565+ - *l2_entry =
566+ - TableDescriptor::from_next_lvl_table_addr(self.lvl3[l2_nr].phys_start_addr_usize());
567+ + /// Doesn't allow overriding an already valid page.
563568+ #[inline(always)]
564- + fn page_descriptor_from (
569+ + fn set_page_descriptor_from_page (
565570+ &mut self,
566- + addr: *const Page<Virtual>,
567- + ) -> Result<&mut PageDescriptor, &'static str> {
568- + let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from(addr)?;
569- +
570- + Ok(&mut self.lvl3[lvl2_index][lvl3_index])
571+ + virt_page: *const Page<Virtual>,
572+ + new_desc: &PageDescriptor,
573+ + ) -> Result<(), &'static str> {
574+ + let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
575+ + let desc = &mut self.lvl3[lvl2_index][lvl3_index];
576+
577+ - for (l3_nr, l3_entry) in self.lvl3[l2_nr].iter_mut().enumerate() {
578+ - let virt_addr = (l2_nr << Granule512MiB::SHIFT) + (l3_nr << Granule64KiB::SHIFT);
579+ + if desc.is_valid() {
580+ + return Err("Virtual page is already mapped");
581+ + }
582+
583+ - let (phys_output_addr, attribute_fields) =
584+ - bsp::memory::mmu::virt_mem_layout().virt_addr_properties(virt_addr)?;
585+ + *desc = *new_desc;
586+ + Ok(())
571587+ }
572588+ }
573- +
589+
590+ - *l3_entry = PageDescriptor::from_output_addr(phys_output_addr, &attribute_fields);
591+ - }
574592+ //------------------------------------------------------------------------------
575593+ // OS Interface Code
576594+ //------------------------------------------------------------------------------
577-
578- - for (l3_nr, l3_entry) in self.lvl3[l2_nr].iter_mut().enumerate() {
579- - let virt_addr = (l2_nr << Granule512MiB::SHIFT) + (l3_nr << Granule64KiB::SHIFT);
595+ +
580596+ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::TranslationTable
581597+ for FixedSizeTranslationTable<NUM_TABLES>
582598+ {
@@ -587,9 +603,10 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
587603+
588604+ // Populate the l2 entries.
589605+ for (lvl2_nr, lvl2_entry) in self.lvl2.iter_mut().enumerate() {
590- + let desc =
591- + TableDescriptor::from_next_lvl_table_addr(self.lvl3[lvl2_nr].phys_start_addr());
592- + *lvl2_entry = desc;
606+ + let phys_table_addr = self.lvl3[lvl2_nr].phys_start_addr();
607+ +
608+ + let new_desc = TableDescriptor::from_next_lvl_table_addr(phys_table_addr);
609+ + *lvl2_entry = new_desc;
593610+ }
594611+
595612+ self.cur_l3_mmio_index = Self::L3_MMIO_START_INDEX;
@@ -608,33 +625,28 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
608625+ ) -> Result<(), &'static str> {
609626+ assert!(self.initialized, "Translation tables not initialized");
610627+
611- + let p = phys_pages.as_slice();
612628+ let v = virt_pages.as_slice();
629+ + let p = phys_pages.as_slice();
613630+
614631+ // No work to do for empty slices.
615632+ if v.is_empty() {
616633+ return Ok(());
617634+ }
618-
619- - let (phys_output_addr, attribute_fields) =
620- - bsp::memory::mmu::virt_mem_layout().virt_addr_properties(virt_addr)?;
635+ +
621636+ if v.len() != p.len() {
622637+ return Err("Tried to map page slices with unequal sizes");
623638+ }
624-
625- - *l3_entry = PageDescriptor::from_output_addr(phys_output_addr, &attribute_fields);
639+ +
626640+ if p.last().unwrap().as_ptr() >= bsp::memory::mmu::phys_addr_space_end_page() {
627641+ return Err("Tried to map outside of physical address space");
628642+ }
629643+
630644+ let iter = p.iter().zip(v.iter());
631645+ for (phys_page, virt_page) in iter {
632- + let page_descriptor = self.page_descriptor_from(virt_page.as_ptr())?;
633- + if page_descriptor.is_valid() {
634- + return Err("Virtual page is already mapped");
635- }
646+ + let new_desc = PageDescriptor::from_output_page(phys_page.as_ptr(), attr);
647+ + let virt_page = virt_page.as_ptr();
636648+
637- + *page_descriptor = PageDescriptor::from_output_addr(phys_page.as_ptr(), attr) ;
649+ + self.set_page_descriptor_from_page(virt_page, &new_desc)? ;
638650 }
639651
640652 Ok(())
@@ -680,7 +692,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/trans
680692 }
681693 }
682694
683- @@ -296,6 +441 ,9 @@
695+ @@ -296,6 +449 ,9 @@
684696 //--------------------------------------------------------------------------------------------------
685697
686698 #[cfg(test)]
@@ -1468,7 +1480,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/link.ld 14_vir
14681480diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs 14_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory/mmu.rs
14691481--- 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
14701482+++ 14_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory/mmu.rs
1471- @@ -4,70 +4,157 @@
1483+ @@ -4,70 +4,150 @@
14721484
14731485 //! BSP Memory Management Unit.
14741486
@@ -1483,7 +1495,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
14831495+ AccessPermissions, AddressSpace, AssociatedTranslationTable, AttributeFields,
14841496+ MemAttributes, Page, PageSliceDescriptor, TranslationGranule,
14851497+ },
1486- + Physical, Virtual,
1498+ + Address, Physical, Virtual,
14871499+ },
14881500+ synchronization::InitStateLock,
14891501+ };
@@ -1504,16 +1516,16 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
15041516+ /// The translation granule chosen by this BSP. This will be used everywhere else in the kernel to
15051517+ /// derive respective data structures and their sizes. For example, the `crate::memory::mmu::Page`.
15061518+ pub type KernelGranule = TranslationGranule<{ 64 * 1024 }>;
1507- +
1519+
1520+ - const NUM_MEM_RANGES: usize = 2;
15081521+ /// The kernel's virtual address space defined by this BSP.
15091522+ pub type KernelVirtAddrSpace = AddressSpace<{ 8 * 1024 * 1024 * 1024 }>;
15101523
1511- - const NUM_MEM_RANGES: usize = 2;
1524+ - /// The virtual memory layout.
15121525+ //--------------------------------------------------------------------------------------------------
15131526+ // Global instances
15141527+ //--------------------------------------------------------------------------------------------------
1515-
1516- - /// The virtual memory layout.
1528+ +
15171529+ /// The kernel translation tables.
15181530 ///
15191531- /// The layout must contain only special ranges, aka anything that is _not_ normal cacheable DRAM.
@@ -1571,8 +1583,10 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
15711583+ let num_pages = size_to_num_pages(super::rx_size());
15721584+
15731585+ PageSliceDescriptor::from_addr(super::virt_rx_start(), num_pages)
1574- + }
1575- +
1586+ }
1587+
1588+ - fn mmio_range_inclusive() -> RangeInclusive<usize> {
1589+ - RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
15761590+ /// The Read+Write (RW) pages of the kernel binary.
15771591+ fn virt_rw_page_desc() -> PageSliceDescriptor<Virtual> {
15781592+ let num_pages = size_to_num_pages(super::rw_size());
@@ -1587,23 +1601,14 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
15871601+ PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
15881602+ }
15891603+
1590- + // The binary is still identity mapped, so we don't need to convert in the following .
1604+ + // The binary is still identity mapped, so use this trivial conversion function for mapping below .
15911605+
1592- + /// The Read+Execute (RX) pages of the kernel binary.
1593- + fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
1594- + virt_rx_page_desc().into()
1595- }
1596-
1597- - fn mmio_range_inclusive() -> RangeInclusive<usize> {
1598- - RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
1599- + /// The Read+Write (RW) pages of the kernel binary.
1600- + fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
1601- + virt_rw_page_desc().into()
1602- + }
1606+ + fn kernel_virt_to_phys_page_slice(
1607+ + virt_slice: PageSliceDescriptor<Virtual>,
1608+ + ) -> PageSliceDescriptor<Physical> {
1609+ + let phys_start_addr = Address::<Physical>::new(virt_slice.start_addr().into_usize());
16031610+
1604- + /// The boot core's stack.
1605- + fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
1606- + virt_boot_core_stack_page_desc().into()
1611+ + PageSliceDescriptor::from_addr(phys_start_addr, virt_slice.num_pages())
16071612 }
16081613
16091614 //--------------------------------------------------------------------------------------------------
@@ -1635,7 +1640,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
16351640+ generic_mmu::kernel_map_pages_at(
16361641+ "Kernel code and RO data",
16371642+ &virt_rx_page_desc(),
1638- + &phys_rx_page_desc( ),
1643+ + &kernel_virt_to_phys_page_slice(virt_rx_page_desc() ),
16391644+ &AttributeFields {
16401645+ mem_attributes: MemAttributes::CacheableDRAM,
16411646+ acc_perms: AccessPermissions::ReadOnly,
@@ -1646,7 +1651,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
16461651+ generic_mmu::kernel_map_pages_at(
16471652+ "Kernel data and bss",
16481653+ &virt_rw_page_desc(),
1649- + &phys_rw_page_desc( ),
1654+ + &kernel_virt_to_phys_page_slice(virt_rw_page_desc() ),
16501655+ &AttributeFields {
16511656+ mem_attributes: MemAttributes::CacheableDRAM,
16521657+ acc_perms: AccessPermissions::ReadWrite,
@@ -1657,7 +1662,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
16571662+ generic_mmu::kernel_map_pages_at(
16581663+ "Kernel boot-core stack",
16591664+ &virt_boot_core_stack_page_desc(),
1660- + &phys_boot_core_stack_page_desc( ),
1665+ + &kernel_virt_to_phys_page_slice(virt_boot_core_stack_page_desc() ),
16611666+ &AttributeFields {
16621667+ mem_attributes: MemAttributes::CacheableDRAM,
16631668+ acc_perms: AccessPermissions::ReadWrite,
@@ -1669,7 +1674,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
16691674 }
16701675
16711676 //--------------------------------------------------------------------------------------------------
1672- @@ -77,19 +164 ,24 @@
1677+ @@ -77,19 +157 ,24 @@
16731678 #[cfg(test)]
16741679 mod tests {
16751680 use super::*;
@@ -1701,7 +1706,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
17011706 assert!(end >= start);
17021707 }
17031708 }
1704- @@ -97,18 +189 ,38 @@
1709+ @@ -97,18 +182 ,38 @@
17051710 /// Ensure the kernel's virtual memory layout is free of overlaps.
17061711 #[kernel_test]
17071712 fn virt_mem_layout_has_no_overlaps() {
@@ -2482,7 +2487,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/translation_table.r
24822487diff -uNr 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/types.rs 14_virtual_mem_part2_mmio_remap/src/memory/mmu/types.rs
24832488--- 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/types.rs
24842489+++ 14_virtual_mem_part2_mmio_remap/src/memory/mmu/types.rs
2485- @@ -0,0 +1,210 @@
2490+ @@ -0,0 +1,201 @@
24862491+ // SPDX-License-Identifier: MIT OR Apache-2.0
24872492+ //
24882493+ // Copyright (c) 2020-2021 Andre Richter <andre.o.richter@gmail.com>
@@ -2491,7 +2496,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/types.rs 14_virtual
24912496+
24922497+ use crate::{
24932498+ bsp, common,
2494- + memory::{Address, AddressType, Physical, Virtual },
2499+ + memory::{Address, AddressType, Physical},
24952500+ };
24962501+ use core::{convert::From, marker::PhantomData};
24972502+
@@ -2577,11 +2582,11 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/types.rs 14_virtual
25772582+ }
25782583+
25792584+ /// Return a pointer to the first page of the described slice.
2580- + const fn first_page_ptr (&self) -> *const Page<ATYPE> {
2585+ + const fn first_page (&self) -> *const Page<ATYPE> {
25812586+ self.start.into_usize() as *const _
25822587+ }
25832588+
2584- + /// Return the number of Pages the slice describes.
2589+ + /// Return the number of pages the slice describes.
25852590+ pub const fn num_pages(&self) -> usize {
25862591+ self.num_pages
25872592+ }
@@ -2611,22 +2616,13 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/src/memory/mmu/types.rs 14_virtual
26112616+ (addr >= self.start_addr()) && (addr <= self.end_addr_inclusive())
26122617+ }
26132618+
2614- + /// Return a non-mutable slice of Pages .
2619+ + /// Return a non-mutable slice of pages .
26152620+ ///
26162621+ /// # Safety
26172622+ ///
26182623+ /// - Same as applies for `core::slice::from_raw_parts`.
26192624+ pub unsafe fn as_slice(&self) -> &[Page<ATYPE>] {
2620- + core::slice::from_raw_parts(self.first_page_ptr(), self.num_pages)
2621- + }
2622- + }
2623- +
2624- + impl From<PageSliceDescriptor<Virtual>> for PageSliceDescriptor<Physical> {
2625- + fn from(desc: PageSliceDescriptor<Virtual>) -> Self {
2626- + Self {
2627- + start: Address::new(desc.start.into_usize()),
2628- + num_pages: desc.num_pages,
2629- + }
2625+ + core::slice::from_raw_parts(self.first_page(), self.num_pages)
26302626+ }
26312627+ }
26322628+
0 commit comments