Skip to content

Commit 57c6f72

Browse files
committed
Make address translation a feature of the tables
1 parent baa634f commit 57c6f72

File tree

20 files changed

+905
-683
lines changed

20 files changed

+905
-683
lines changed

14_virtual_mem_part2_mmio_remap/README.md

Lines changed: 79 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -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
14681480
diff -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
24822487
diff -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

Comments
 (0)