Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 57c6f72

Browse files
committedNov 13, 2021
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
+

‎14_virtual_mem_part2_mmio_remap/src/_arch/aarch64/memory/mmu/translation_table.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,13 @@ impl PageDescriptor {
229229
}
230230

231231
/// Create an instance.
232-
pub fn from_output_addr(
233-
phys_output_addr: *const Page<Physical>,
232+
pub fn from_output_page(
233+
phys_output_page: *const Page<Physical>,
234234
attribute_fields: &AttributeFields,
235235
) -> Self {
236236
let val = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(0);
237237

238-
let shifted = phys_output_addr as u64 >> Granule64KiB::SHIFT;
238+
let shifted = phys_output_page as u64 >> Granule64KiB::SHIFT;
239239
val.write(
240240
STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB.val(shifted)
241241
+ STAGE1_PAGE_DESCRIPTOR::AF::True
@@ -308,11 +308,11 @@ impl<const NUM_TABLES: usize> FixedSizeTranslationTable<NUM_TABLES> {
308308

309309
/// Helper to calculate the lvl2 and lvl3 indices from an address.
310310
#[inline(always)]
311-
fn lvl2_lvl3_index_from(
311+
fn lvl2_lvl3_index_from_page(
312312
&self,
313-
addr: *const Page<Virtual>,
313+
virt_page: *const Page<Virtual>,
314314
) -> Result<(usize, usize), &'static str> {
315-
let addr = addr as usize;
315+
let addr = virt_page as usize;
316316
let lvl2_index = addr >> Granule512MiB::SHIFT;
317317
let lvl3_index = (addr & Granule512MiB::MASK) >> Granule64KiB::SHIFT;
318318

@@ -323,15 +323,24 @@ impl<const NUM_TABLES: usize> FixedSizeTranslationTable<NUM_TABLES> {
323323
Ok((lvl2_index, lvl3_index))
324324
}
325325

326-
/// Returns the PageDescriptor corresponding to the supplied Page.
326+
/// Sets the PageDescriptor corresponding to the supplied page address.
327+
///
328+
/// Doesn't allow overriding an already valid page.
327329
#[inline(always)]
328-
fn page_descriptor_from(
330+
fn set_page_descriptor_from_page(
329331
&mut self,
330-
addr: *const Page<Virtual>,
331-
) -> Result<&mut PageDescriptor, &'static str> {
332-
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from(addr)?;
332+
virt_page: *const Page<Virtual>,
333+
new_desc: &PageDescriptor,
334+
) -> Result<(), &'static str> {
335+
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
336+
let desc = &mut self.lvl3[lvl2_index][lvl3_index];
333337

334-
Ok(&mut self.lvl3[lvl2_index][lvl3_index])
338+
if desc.is_valid() {
339+
return Err("Virtual page is already mapped");
340+
}
341+
342+
*desc = *new_desc;
343+
Ok(())
335344
}
336345
}
337346

@@ -349,9 +358,10 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
349358

350359
// Populate the l2 entries.
351360
for (lvl2_nr, lvl2_entry) in self.lvl2.iter_mut().enumerate() {
352-
let desc =
353-
TableDescriptor::from_next_lvl_table_addr(self.lvl3[lvl2_nr].phys_start_addr());
354-
*lvl2_entry = desc;
361+
let phys_table_addr = self.lvl3[lvl2_nr].phys_start_addr();
362+
363+
let new_desc = TableDescriptor::from_next_lvl_table_addr(phys_table_addr);
364+
*lvl2_entry = new_desc;
355365
}
356366

357367
self.cur_l3_mmio_index = Self::L3_MMIO_START_INDEX;
@@ -370,8 +380,8 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
370380
) -> Result<(), &'static str> {
371381
assert!(self.initialized, "Translation tables not initialized");
372382

373-
let p = phys_pages.as_slice();
374383
let v = virt_pages.as_slice();
384+
let p = phys_pages.as_slice();
375385

376386
// No work to do for empty slices.
377387
if v.is_empty() {
@@ -388,12 +398,10 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
388398

389399
let iter = p.iter().zip(v.iter());
390400
for (phys_page, virt_page) in iter {
391-
let page_descriptor = self.page_descriptor_from(virt_page.as_ptr())?;
392-
if page_descriptor.is_valid() {
393-
return Err("Virtual page is already mapped");
394-
}
401+
let new_desc = PageDescriptor::from_output_page(phys_page.as_ptr(), attr);
402+
let virt_page = virt_page.as_ptr();
395403

396-
*page_descriptor = PageDescriptor::from_output_addr(phys_page.as_ptr(), attr);
404+
self.set_page_descriptor_from_page(virt_page, &new_desc)?;
397405
}
398406

399407
Ok(())

‎14_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory/mmu.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
AccessPermissions, AddressSpace, AssociatedTranslationTable, AttributeFields,
1313
MemAttributes, Page, PageSliceDescriptor, TranslationGranule,
1414
},
15-
Physical, Virtual,
15+
Address, Physical, Virtual,
1616
},
1717
synchronization::InitStateLock,
1818
};
@@ -81,21 +81,14 @@ fn virt_boot_core_stack_page_desc() -> PageSliceDescriptor<Virtual> {
8181
PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
8282
}
8383

84-
// The binary is still identity mapped, so we don't need to convert in the following.
84+
// The binary is still identity mapped, so use this trivial conversion function for mapping below.
8585

86-
/// The Read+Execute (RX) pages of the kernel binary.
87-
fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
88-
virt_rx_page_desc().into()
89-
}
90-
91-
/// The Read+Write (RW) pages of the kernel binary.
92-
fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
93-
virt_rw_page_desc().into()
94-
}
86+
fn kernel_virt_to_phys_page_slice(
87+
virt_slice: PageSliceDescriptor<Virtual>,
88+
) -> PageSliceDescriptor<Physical> {
89+
let phys_start_addr = Address::<Physical>::new(virt_slice.start_addr().into_usize());
9590

96-
/// The boot core's stack.
97-
fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
98-
virt_boot_core_stack_page_desc().into()
91+
PageSliceDescriptor::from_addr(phys_start_addr, virt_slice.num_pages())
9992
}
10093

10194
//--------------------------------------------------------------------------------------------------
@@ -124,7 +117,7 @@ pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
124117
generic_mmu::kernel_map_pages_at(
125118
"Kernel code and RO data",
126119
&virt_rx_page_desc(),
127-
&phys_rx_page_desc(),
120+
&kernel_virt_to_phys_page_slice(virt_rx_page_desc()),
128121
&AttributeFields {
129122
mem_attributes: MemAttributes::CacheableDRAM,
130123
acc_perms: AccessPermissions::ReadOnly,
@@ -135,7 +128,7 @@ pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
135128
generic_mmu::kernel_map_pages_at(
136129
"Kernel data and bss",
137130
&virt_rw_page_desc(),
138-
&phys_rw_page_desc(),
131+
&kernel_virt_to_phys_page_slice(virt_rw_page_desc()),
139132
&AttributeFields {
140133
mem_attributes: MemAttributes::CacheableDRAM,
141134
acc_perms: AccessPermissions::ReadWrite,
@@ -146,7 +139,7 @@ pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
146139
generic_mmu::kernel_map_pages_at(
147140
"Kernel boot-core stack",
148141
&virt_boot_core_stack_page_desc(),
149-
&phys_boot_core_stack_page_desc(),
142+
&kernel_virt_to_phys_page_slice(virt_boot_core_stack_page_desc()),
150143
&AttributeFields {
151144
mem_attributes: MemAttributes::CacheableDRAM,
152145
acc_perms: AccessPermissions::ReadWrite,

‎14_virtual_mem_part2_mmio_remap/src/memory/mmu/types.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use crate::{
88
bsp, common,
9-
memory::{Address, AddressType, Physical, Virtual},
9+
memory::{Address, AddressType, Physical},
1010
};
1111
use core::{convert::From, marker::PhantomData};
1212

@@ -92,11 +92,11 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
9292
}
9393

9494
/// Return a pointer to the first page of the described slice.
95-
const fn first_page_ptr(&self) -> *const Page<ATYPE> {
95+
const fn first_page(&self) -> *const Page<ATYPE> {
9696
self.start.into_usize() as *const _
9797
}
9898

99-
/// Return the number of Pages the slice describes.
99+
/// Return the number of pages the slice describes.
100100
pub const fn num_pages(&self) -> usize {
101101
self.num_pages
102102
}
@@ -126,22 +126,13 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
126126
(addr >= self.start_addr()) && (addr <= self.end_addr_inclusive())
127127
}
128128

129-
/// Return a non-mutable slice of Pages.
129+
/// Return a non-mutable slice of pages.
130130
///
131131
/// # Safety
132132
///
133133
/// - Same as applies for `core::slice::from_raw_parts`.
134134
pub unsafe fn as_slice(&self) -> &[Page<ATYPE>] {
135-
core::slice::from_raw_parts(self.first_page_ptr(), self.num_pages)
136-
}
137-
}
138-
139-
impl From<PageSliceDescriptor<Virtual>> for PageSliceDescriptor<Physical> {
140-
fn from(desc: PageSliceDescriptor<Virtual>) -> Self {
141-
Self {
142-
start: Address::new(desc.start.into_usize()),
143-
num_pages: desc.num_pages,
144-
}
135+
core::slice::from_raw_parts(self.first_page(), self.num_pages)
145136
}
146137
}
147138

‎15_virtual_mem_part3_precomputed_tables/README.md

Lines changed: 295 additions & 216 deletions
Large diffs are not rendered by default.

‎15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu.rs

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
use crate::{
1717
bsp, memory,
18-
memory::{mmu::TranslationGranule, Address, Physical, Virtual},
18+
memory::{mmu::TranslationGranule, Address, Physical},
1919
};
2020
use core::intrinsics::unlikely;
2121
use cortex_a::{asm::barrier, registers::*};
@@ -109,7 +109,7 @@ pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
109109
//------------------------------------------------------------------------------
110110
// OS Interface Code
111111
//------------------------------------------------------------------------------
112-
use memory::mmu::{MMUEnableError, TranslationError};
112+
use memory::mmu::MMUEnableError;
113113

114114
impl memory::mmu::interface::MMU for MemoryManagementUnit {
115115
unsafe fn enable_mmu_and_caching(
@@ -153,31 +153,4 @@ impl memory::mmu::interface::MMU for MemoryManagementUnit {
153153
fn is_enabled(&self) -> bool {
154154
SCTLR_EL1.matches_all(SCTLR_EL1::M::Enable)
155155
}
156-
157-
fn try_virt_to_phys(
158-
&self,
159-
virt: Address<Virtual>,
160-
) -> Result<Address<Physical>, TranslationError> {
161-
if !self.is_enabled() {
162-
return Err(TranslationError::MMUDisabled);
163-
}
164-
165-
let addr = virt.into_usize() as u64;
166-
unsafe {
167-
asm!(
168-
"AT S1E1R, {0}",
169-
in(reg) addr,
170-
options(readonly, nostack, preserves_flags)
171-
);
172-
}
173-
174-
let par_el1 = PAR_EL1.extract();
175-
if par_el1.matches_all(PAR_EL1::F::TranslationAborted) {
176-
return Err(TranslationError::Aborted);
177-
}
178-
179-
let phys_addr = (par_el1.read(PAR_EL1::PA) << 12) | (addr & 0xFFF);
180-
181-
Ok(Address::new(phys_addr as usize))
182-
}
183156
}

‎15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/translation_table.rs

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
Address, Physical, Virtual,
2424
},
2525
};
26-
use core::convert::{self, TryInto};
26+
use core::convert;
2727
use tock_registers::{
2828
interfaces::{Readable, Writeable},
2929
register_bitfields,
@@ -219,6 +219,35 @@ impl convert::From<AttributeFields>
219219
}
220220
}
221221

222+
/// Convert the HW-specific attributes of the MMU to kernel's generic memory attributes.
223+
impl convert::TryFrom<InMemoryRegister<u64, STAGE1_PAGE_DESCRIPTOR::Register>> for AttributeFields {
224+
type Error = &'static str;
225+
226+
fn try_from(
227+
desc: InMemoryRegister<u64, STAGE1_PAGE_DESCRIPTOR::Register>,
228+
) -> Result<AttributeFields, Self::Error> {
229+
let mem_attributes = match desc.read(STAGE1_PAGE_DESCRIPTOR::AttrIndx) {
230+
memory::mmu::arch_mmu::mair::NORMAL => MemAttributes::CacheableDRAM,
231+
memory::mmu::arch_mmu::mair::DEVICE => MemAttributes::Device,
232+
_ => return Err("Unexpected memory attribute"),
233+
};
234+
235+
let acc_perms = match desc.read_as_enum(STAGE1_PAGE_DESCRIPTOR::AP) {
236+
Some(STAGE1_PAGE_DESCRIPTOR::AP::Value::RO_EL1) => AccessPermissions::ReadOnly,
237+
Some(STAGE1_PAGE_DESCRIPTOR::AP::Value::RW_EL1) => AccessPermissions::ReadWrite,
238+
_ => return Err("Unexpected access permission"),
239+
};
240+
241+
let execute_never = desc.read(STAGE1_PAGE_DESCRIPTOR::PXN) > 0;
242+
243+
Ok(AttributeFields {
244+
mem_attributes,
245+
acc_perms,
246+
execute_never,
247+
})
248+
}
249+
}
250+
222251
impl PageDescriptor {
223252
/// Create an instance.
224253
///
@@ -228,13 +257,13 @@ impl PageDescriptor {
228257
}
229258

230259
/// Create an instance.
231-
pub fn from_output_addr(
232-
phys_output_addr: *const Page<Physical>,
260+
pub fn from_output_page(
261+
phys_output_page: *const Page<Physical>,
233262
attribute_fields: &AttributeFields,
234263
) -> Self {
235264
let val = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(0);
236265

237-
let shifted = phys_output_addr as u64 >> Granule64KiB::SHIFT;
266+
let shifted = phys_output_page as u64 >> Granule64KiB::SHIFT;
238267
val.write(
239268
STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB.val(shifted)
240269
+ STAGE1_PAGE_DESCRIPTOR::AF::True
@@ -251,6 +280,20 @@ impl PageDescriptor {
251280
InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value)
252281
.is_set(STAGE1_PAGE_DESCRIPTOR::VALID)
253282
}
283+
284+
/// Returns the output page.
285+
fn output_page(&self) -> *const Page<Physical> {
286+
let shifted = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value)
287+
.read(STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB);
288+
let addr = shifted << Granule64KiB::SHIFT;
289+
290+
addr as *const Page<Physical>
291+
}
292+
293+
/// Returns the attributes.
294+
fn try_attributes(&self) -> Result<AttributeFields, &'static str> {
295+
InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value).try_into()
296+
}
254297
}
255298

256299
//--------------------------------------------------------------------------------------------------
@@ -316,11 +359,11 @@ impl<const NUM_TABLES: usize> FixedSizeTranslationTable<NUM_TABLES> {
316359

317360
/// Helper to calculate the lvl2 and lvl3 indices from an address.
318361
#[inline(always)]
319-
fn lvl2_lvl3_index_from(
362+
fn lvl2_lvl3_index_from_page(
320363
&self,
321-
addr: *const Page<Virtual>,
364+
virt_page: *const Page<Virtual>,
322365
) -> Result<(usize, usize), &'static str> {
323-
let addr = addr as usize;
366+
let addr = virt_page as usize;
324367
let lvl2_index = addr >> Granule512MiB::SHIFT;
325368
let lvl3_index = (addr & Granule512MiB::MASK) >> Granule64KiB::SHIFT;
326369

@@ -331,15 +374,36 @@ impl<const NUM_TABLES: usize> FixedSizeTranslationTable<NUM_TABLES> {
331374
Ok((lvl2_index, lvl3_index))
332375
}
333376

334-
/// Returns the PageDescriptor corresponding to the supplied Page.
377+
/// Returns the PageDescriptor corresponding to the supplied page address.
335378
#[inline(always)]
336-
fn page_descriptor_from(
379+
fn page_descriptor_from_page(
380+
&self,
381+
virt_page: *const Page<Virtual>,
382+
) -> Result<&PageDescriptor, &'static str> {
383+
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
384+
let desc = &self.lvl3[lvl2_index][lvl3_index];
385+
386+
Ok(desc)
387+
}
388+
389+
/// Sets the PageDescriptor corresponding to the supplied page address.
390+
///
391+
/// Doesn't allow overriding an already valid page.
392+
#[inline(always)]
393+
fn set_page_descriptor_from_page(
337394
&mut self,
338-
addr: *const Page<Virtual>,
339-
) -> Result<&mut PageDescriptor, &'static str> {
340-
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from(addr)?;
395+
virt_page: *const Page<Virtual>,
396+
new_desc: &PageDescriptor,
397+
) -> Result<(), &'static str> {
398+
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
399+
let desc = &mut self.lvl3[lvl2_index][lvl3_index];
400+
401+
if desc.is_valid() {
402+
return Err("Virtual page is already mapped");
403+
}
341404

342-
Ok(&mut self.lvl3[lvl2_index][lvl3_index])
405+
*desc = *new_desc;
406+
Ok(())
343407
}
344408
}
345409

@@ -357,13 +421,11 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
357421

358422
// Populate the l2 entries.
359423
for (lvl2_nr, lvl2_entry) in self.lvl2.iter_mut().enumerate() {
360-
let addr = self.lvl3[lvl2_nr]
361-
.virt_start_addr()
362-
.try_into()
363-
.map_err(|_| "Translation error")?;
424+
let virt_table_addr = self.lvl3[lvl2_nr].virt_start_addr();
425+
let phys_table_addr = memory::mmu::try_kernel_virt_addr_to_phys_addr(virt_table_addr)?;
364426

365-
let desc = TableDescriptor::from_next_lvl_table_addr(addr);
366-
*lvl2_entry = desc;
427+
let new_desc = TableDescriptor::from_next_lvl_table_addr(phys_table_addr);
428+
*lvl2_entry = new_desc;
367429
}
368430

369431
self.cur_l3_mmio_index = Self::L3_MMIO_START_INDEX;
@@ -380,8 +442,8 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
380442
) -> Result<(), &'static str> {
381443
assert!(self.initialized, "Translation tables not initialized");
382444

383-
let p = phys_pages.as_slice();
384445
let v = virt_pages.as_slice();
446+
let p = phys_pages.as_slice();
385447

386448
// No work to do for empty slices.
387449
if v.is_empty() {
@@ -398,12 +460,10 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
398460

399461
let iter = p.iter().zip(v.iter());
400462
for (phys_page, virt_page) in iter {
401-
let page_descriptor = self.page_descriptor_from(virt_page.as_ptr())?;
402-
if page_descriptor.is_valid() {
403-
return Err("Virtual page is already mapped");
404-
}
463+
let new_desc = PageDescriptor::from_output_page(phys_page.as_ptr(), attr);
464+
let virt_page = virt_page.as_ptr();
405465

406-
*page_descriptor = PageDescriptor::from_output_addr(phys_page.as_ptr(), attr);
466+
self.set_page_descriptor_from_page(virt_page, &new_desc)?;
407467
}
408468

409469
Ok(())
@@ -444,6 +504,44 @@ impl<const NUM_TABLES: usize> memory::mmu::translation_table::interface::Transla
444504

445505
false
446506
}
507+
508+
fn try_virt_page_to_phys_page(
509+
&self,
510+
virt_page: *const Page<Virtual>,
511+
) -> Result<*const Page<Physical>, &'static str> {
512+
let page_desc = self.page_descriptor_from_page(virt_page)?;
513+
514+
if !page_desc.is_valid() {
515+
return Err("Page marked invalid");
516+
}
517+
518+
Ok(page_desc.output_page())
519+
}
520+
521+
fn try_page_attributes(
522+
&self,
523+
virt_page: *const Page<Virtual>,
524+
) -> Result<AttributeFields, &'static str> {
525+
let page_desc = self.page_descriptor_from_page(virt_page)?;
526+
527+
if !page_desc.is_valid() {
528+
return Err("Page marked invalid");
529+
}
530+
531+
page_desc.try_attributes()
532+
}
533+
534+
/// Try to translate a virtual address to a physical address.
535+
///
536+
/// Will only succeed if there exists a valid mapping for the input address.
537+
fn try_virt_addr_to_phys_addr(
538+
&self,
539+
virt_addr: Address<Virtual>,
540+
) -> Result<Address<Physical>, &'static str> {
541+
let page = self.try_virt_page_to_phys_page(virt_addr.as_page_ptr())?;
542+
543+
Ok(Address::new(page as usize + virt_addr.offset_into_page()))
544+
}
447545
}
448546

449547
//--------------------------------------------------------------------------------------------------

‎15_virtual_mem_part3_precomputed_tables/src/bsp/raspberrypi/memory/mmu.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ use crate::{
99
memory::{
1010
mmu as generic_mmu,
1111
mmu::{
12-
AccessPermissions, AddressSpace, AssociatedTranslationTable, AttributeFields,
13-
MemAttributes, Page, PageSliceDescriptor, TranslationGranule,
12+
AddressSpace, AssociatedTranslationTable, AttributeFields, Page, PageSliceDescriptor,
13+
TranslationGranule,
1414
},
15-
Physical, Virtual,
15+
Address, Physical, Virtual,
1616
},
1717
synchronization::InitStateLock,
1818
};
19-
use core::convert::TryInto;
2019

2120
//--------------------------------------------------------------------------------------------------
2221
// Private Definitions
@@ -103,21 +102,19 @@ fn virt_boot_core_stack_page_desc() -> PageSliceDescriptor<Virtual> {
103102
}
104103

105104
// There is no reason to expect the following conversions to fail, since they were generated offline
106-
// by the `translation table tool`. If it doesn't work, a panic due to the unwrap is justified.
107-
108-
/// The Read+Execute (RX) pages of the kernel binary.
109-
fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
110-
virt_rx_page_desc().try_into().unwrap()
111-
}
112-
113-
/// The Read+Write (RW) pages of the kernel binary.
114-
fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
115-
virt_rw_page_desc().try_into().unwrap()
105+
// by the `translation table tool`. If it doesn't work, a panic due to the unwraps is justified.
106+
fn kernel_virt_to_phys_page_slice(
107+
virt_slice: PageSliceDescriptor<Virtual>,
108+
) -> PageSliceDescriptor<Physical> {
109+
let phys_first_page =
110+
generic_mmu::try_kernel_virt_page_to_phys_page(virt_slice.first_page()).unwrap();
111+
let phys_start_addr = Address::new(phys_first_page as usize);
112+
113+
PageSliceDescriptor::from_addr(phys_start_addr, virt_slice.num_pages())
116114
}
117115

118-
/// The boot core's stack.
119-
fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
120-
virt_boot_core_stack_page_desc().try_into().unwrap()
116+
fn kernel_page_attributes(virt_page: *const Page<Virtual>) -> AttributeFields {
117+
generic_mmu::try_kernel_page_attributes(virt_page).unwrap()
121118
}
122119

123120
//--------------------------------------------------------------------------------------------------
@@ -142,39 +139,28 @@ pub fn phys_addr_space_end_page() -> *const Page<Physical> {
142139
/// The actual translation table entries for the kernel binary are generated using the offline
143140
/// `translation table tool` and patched into the kernel binary. This function just adds the mapping
144141
/// record entries.
145-
///
146-
/// It must be ensured that these entries are in sync with the offline tool.
147142
pub fn kernel_add_mapping_records_for_precomputed() {
143+
let virt_rx_page_desc = virt_rx_page_desc();
148144
generic_mmu::kernel_add_mapping_record(
149145
"Kernel code and RO data",
150-
&virt_rx_page_desc(),
151-
&phys_rx_page_desc(),
152-
&AttributeFields {
153-
mem_attributes: MemAttributes::CacheableDRAM,
154-
acc_perms: AccessPermissions::ReadOnly,
155-
execute_never: false,
156-
},
146+
&virt_rx_page_desc,
147+
&kernel_virt_to_phys_page_slice(virt_rx_page_desc),
148+
&kernel_page_attributes(virt_rx_page_desc.first_page()),
157149
);
158150

151+
let virt_rw_page_desc = virt_rw_page_desc();
159152
generic_mmu::kernel_add_mapping_record(
160153
"Kernel data and bss",
161-
&virt_rw_page_desc(),
162-
&phys_rw_page_desc(),
163-
&AttributeFields {
164-
mem_attributes: MemAttributes::CacheableDRAM,
165-
acc_perms: AccessPermissions::ReadWrite,
166-
execute_never: true,
167-
},
154+
&virt_rw_page_desc,
155+
&kernel_virt_to_phys_page_slice(virt_rw_page_desc),
156+
&kernel_page_attributes(virt_rw_page_desc.first_page()),
168157
);
169158

159+
let virt_boot_core_stack_page_desc = virt_boot_core_stack_page_desc();
170160
generic_mmu::kernel_add_mapping_record(
171161
"Kernel boot-core stack",
172-
&virt_boot_core_stack_page_desc(),
173-
&phys_boot_core_stack_page_desc(),
174-
&AttributeFields {
175-
mem_attributes: MemAttributes::CacheableDRAM,
176-
acc_perms: AccessPermissions::ReadWrite,
177-
execute_never: true,
178-
},
162+
&virt_boot_core_stack_page_desc,
163+
&kernel_virt_to_phys_page_slice(virt_boot_core_stack_page_desc),
164+
&kernel_page_attributes(virt_boot_core_stack_page_desc.first_page()),
179165
);
180166
}

‎15_virtual_mem_part3_precomputed_tables/src/memory.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
77
pub mod mmu;
88

9-
use crate::common;
9+
use crate::{bsp, common};
1010
use core::{
11-
convert::TryFrom,
1211
fmt,
1312
marker::PhantomData,
1413
ops::{AddAssign, SubAssign},
1514
};
15+
use mmu::Page;
1616

1717
//--------------------------------------------------------------------------------------------------
1818
// Public Definitions
@@ -66,13 +66,16 @@ impl<ATYPE: AddressType> Address<ATYPE> {
6666
pub const fn into_usize(self) -> usize {
6767
self.value
6868
}
69-
}
7069

71-
impl TryFrom<Address<Virtual>> for Address<Physical> {
72-
type Error = mmu::TranslationError;
70+
/// Return a pointer to the page that contains this address.
71+
pub const fn as_page_ptr(&self) -> *const Page<ATYPE> {
72+
self.align_down(bsp::memory::mmu::KernelGranule::SIZE)
73+
.into_usize() as *const _
74+
}
7375

74-
fn try_from(virt: Address<Virtual>) -> Result<Self, Self::Error> {
75-
mmu::try_virt_to_phys(virt)
76+
/// Return the address' offset into the underlying page.
77+
pub const fn offset_into_page(&self) -> usize {
78+
self.value & bsp::memory::mmu::KernelGranule::MASK
7679
}
7780
}
7881

‎15_virtual_mem_part3_precomputed_tables/src/memory/mmu.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,6 @@ pub enum MMUEnableError {
3333
Other(&'static str),
3434
}
3535

36-
/// Translation error variants.
37-
#[allow(missing_docs)]
38-
#[derive(Debug)]
39-
pub enum TranslationError {
40-
MMUDisabled,
41-
Aborted,
42-
}
43-
4436
/// Memory Management interfaces.
4537
pub mod interface {
4638
use super::*;
@@ -59,14 +51,6 @@ pub mod interface {
5951

6052
/// Returns true if the MMU is enabled, false otherwise.
6153
fn is_enabled(&self) -> bool;
62-
63-
/// Try to translate a virtual address to a physical address.
64-
///
65-
/// Will only succeed if there exists a valid mapping for the input VA.
66-
fn try_virt_to_phys(
67-
&self,
68-
virt: Address<Virtual>,
69-
) -> Result<Address<Physical>, TranslationError>;
7054
}
7155
}
7256

@@ -240,11 +224,34 @@ pub unsafe fn kernel_map_mmio(
240224
Ok(virt_addr + offset_into_start_page)
241225
}
242226

243-
/// Try to translate a virtual address to a physical address.
227+
/// Try to translate a kernel virtual page pointer to a physical page pointer.
228+
///
229+
/// Will only succeed if there exists a valid mapping for the input page.
230+
pub fn try_kernel_virt_page_to_phys_page(
231+
virt_page: *const Page<Virtual>,
232+
) -> Result<*const Page<Physical>, &'static str> {
233+
bsp::memory::mmu::kernel_translation_tables()
234+
.read(|tables| tables.try_virt_page_to_phys_page(virt_page))
235+
}
236+
237+
/// Try to get the attributes of a kernel page.
238+
///
239+
/// Will only succeed if there exists a valid mapping for the input page.
240+
pub fn try_kernel_page_attributes(
241+
virt_page: *const Page<Virtual>,
242+
) -> Result<AttributeFields, &'static str> {
243+
bsp::memory::mmu::kernel_translation_tables()
244+
.read(|tables| tables.try_page_attributes(virt_page))
245+
}
246+
247+
/// Try to translate a kernel virtual address to a physical address.
244248
///
245-
/// Will only succeed if there exists a valid mapping for the input VA.
246-
pub fn try_virt_to_phys(virt: Address<Virtual>) -> Result<Address<Physical>, TranslationError> {
247-
arch_mmu::mmu().try_virt_to_phys(virt)
249+
/// Will only succeed if there exists a valid mapping for the input address.
250+
fn try_kernel_virt_addr_to_phys_addr(
251+
virt_addr: Address<Virtual>,
252+
) -> Result<Address<Physical>, &'static str> {
253+
bsp::memory::mmu::kernel_translation_tables()
254+
.read(|tables| tables.try_virt_addr_to_phys_addr(virt_addr))
248255
}
249256

250257
/// Enable the MMU and data + instruction caching.

‎15_virtual_mem_part3_precomputed_tables/src/memory/mmu/translation_table.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod arch_translation_table;
1010

1111
use crate::memory::{
1212
mmu::{AttributeFields, PageSliceDescriptor},
13-
Physical, Virtual,
13+
Address, Page, Physical, Virtual,
1414
};
1515

1616
//--------------------------------------------------------------------------------------------------
@@ -67,6 +67,30 @@ pub mod interface {
6767

6868
/// Check if a virtual page splice is in the "MMIO region".
6969
fn is_virt_page_slice_mmio(&self, virt_pages: &PageSliceDescriptor<Virtual>) -> bool;
70+
71+
/// Try to translate a virtual page pointer to a physical page pointer.
72+
///
73+
/// Will only succeed if there exists a valid mapping for the input page.
74+
fn try_virt_page_to_phys_page(
75+
&self,
76+
virt_page: *const Page<Virtual>,
77+
) -> Result<*const Page<Physical>, &'static str>;
78+
79+
/// Try to get the attributes of a page.
80+
///
81+
/// Will only succeed if there exists a valid mapping for the input page.
82+
fn try_page_attributes(
83+
&self,
84+
virt_page: *const Page<Virtual>,
85+
) -> Result<AttributeFields, &'static str>;
86+
87+
/// Try to translate a virtual address to a physical address.
88+
///
89+
/// Will only succeed if there exists a valid mapping for the input address.
90+
fn try_virt_addr_to_phys_addr(
91+
&self,
92+
virt_addr: Address<Virtual>,
93+
) -> Result<Address<Physical>, &'static str>;
7094
}
7195
}
7296

‎15_virtual_mem_part3_precomputed_tables/src/memory/mmu/types.rs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
77
use crate::{
88
bsp, common,
9-
memory::{Address, AddressType, Physical, Virtual},
10-
};
11-
use core::{
12-
convert::{From, TryFrom},
13-
marker::PhantomData,
9+
memory::{Address, AddressType, Physical},
1410
};
11+
use core::{convert::From, marker::PhantomData};
1512

1613
//--------------------------------------------------------------------------------------------------
1714
// Public Definitions
@@ -95,11 +92,11 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
9592
}
9693

9794
/// Return a pointer to the first page of the described slice.
98-
const fn first_page_ptr(&self) -> *const Page<ATYPE> {
95+
pub const fn first_page(&self) -> *const Page<ATYPE> {
9996
self.start.into_usize() as *const _
10097
}
10198

102-
/// Return the number of Pages the slice describes.
99+
/// Return the number of pages the slice describes.
103100
pub const fn num_pages(&self) -> usize {
104101
self.num_pages
105102
}
@@ -129,26 +126,13 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
129126
(addr >= self.start_addr()) && (addr <= self.end_addr_inclusive())
130127
}
131128

132-
/// Return a non-mutable slice of Pages.
129+
/// Return a non-mutable slice of pages.
133130
///
134131
/// # Safety
135132
///
136133
/// - Same as applies for `core::slice::from_raw_parts`.
137134
pub unsafe fn as_slice(&self) -> &[Page<ATYPE>] {
138-
core::slice::from_raw_parts(self.first_page_ptr(), self.num_pages)
139-
}
140-
}
141-
142-
impl TryFrom<PageSliceDescriptor<Virtual>> for PageSliceDescriptor<Physical> {
143-
type Error = super::TranslationError;
144-
145-
fn try_from(desc: PageSliceDescriptor<Virtual>) -> Result<Self, Self::Error> {
146-
let phys_start = super::try_virt_to_phys(desc.start)?;
147-
148-
Ok(Self {
149-
start: phys_start,
150-
num_pages: desc.num_pages,
151-
})
135+
core::slice::from_raw_parts(self.first_page(), self.num_pages)
152136
}
153137
}
154138

‎16_virtual_mem_part4_higher_half_kernel/README.md

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,15 @@ Precomputing kernel translation tables and patching kernel ELF
144144
Generating Boot-core stack | 0xffff_ffff_8010_0000 | 512 KiB
145145
--------------------------------------------------
146146
Patching Kernel table struct at physical 0x9_0000
147-
Patching Value of kernel table physical base address (0xd_0000) at physical 0x8_0060
147+
Patching Value of kernel table physical base address (0xd_0000) at physical 0x8_0080
148148
Finished in 0.03s
149149

150150
Minipush 1.0
151151

152152
[MP] ⏳ Waiting for /dev/ttyUSB0
153153
[MP] ✅ Serial connected
154154
[MP] 🔌 Please power the target now
155+
155156
__ __ _ _ _ _
156157
| \/ (_)_ _ (_) | ___ __ _ __| |
157158
| |\/| | | ' \| | |__/ _ \/ _` / _` |
@@ -163,19 +164,20 @@ Minipush 1.0
163164
[MP] ⏩ Pushing 387 KiB =======================================🦀 100% 96 KiB/s Time: 00:00:04
164165
[ML] Loaded! Executing the payload now
165166

166-
[ 4.316420] mingo version 0.16.0
167-
[ 4.316627] Booting on: Raspberry Pi 3
168-
[ 4.317082] MMU online:
169-
[ 4.317375] -------------------------------------------------------------------------------------------------------------------------------------------
170-
[ 4.319119] Virtual Physical Size Attr Entity
171-
[ 4.320863] -------------------------------------------------------------------------------------------------------------------------------------------
172-
[ 4.322610] 0xffff_ffff_8008_0000..0xffff_ffff_8008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
173-
[ 4.324223] 0xffff_ffff_8009_0000..0xffff_ffff_800e_ffff --> 0x00_0009_0000..0x00_000e_ffff | 384 KiB | C RW XN | Kernel data and bss
174-
[ 4.325793] 0xffff_ffff_8010_0000..0xffff_ffff_8017_ffff --> 0x00_0010_0000..0x00_0017_ffff | 512 KiB | C RW XN | Kernel boot-core stack
175-
[ 4.327397] 0xffff_ffff_f000_0000..0xffff_ffff_f000_ffff --> 0x00_3f20_0000..0x00_3f20_ffff | 64 KiB | Dev RW XN | BCM GPIO
176-
[ 4.328847] | BCM PL011 UART
177-
[ 4.330365] 0xffff_ffff_f001_0000..0xffff_ffff_f001_ffff --> 0x00_3f00_0000..0x00_3f00_ffff | 64 KiB | Dev RW XN | BCM Peripheral Interrupt Controller
178-
[ 4.332108] -------------------------------------------------------------------------------------------------------------------------------------------
167+
[ 4.318584] mingo version 0.16.0
168+
[ 4.318792] Booting on: Raspberry Pi 3
169+
[ 4.319247] MMU online:
170+
[ 4.319540] -------------------------------------------------------------------------------------------------------------------------------------------
171+
[ 4.321284] Virtual Physical Size Attr Entity
172+
[ 4.323028] -------------------------------------------------------------------------------------------------------------------------------------------
173+
[ 4.324773] 0xffff_ffff_8008_0000..0xffff_ffff_8008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
174+
[ 4.326387] 0xffff_ffff_8009_0000..0xffff_ffff_800e_ffff --> 0x00_0009_0000..0x00_000e_ffff | 384 KiB | C RW XN | Kernel data and bss
175+
[ 4.327957] 0xffff_ffff_8010_0000..0xffff_ffff_8017_ffff --> 0x00_0010_0000..0x00_0017_ffff | 512 KiB | C RW XN | Kernel boot-core stack
176+
[ 4.329560] 0xffff_ffff_f000_0000..0xffff_ffff_f000_ffff --> 0x00_3f20_0000..0x00_3f20_ffff | 64 KiB | Dev RW XN | BCM GPIO
177+
[ 4.331012] | BCM PL011 UART
178+
[ 4.332529] 0xffff_ffff_f001_0000..0xffff_ffff_f001_ffff --> 0x00_3f00_0000..0x00_3f00_ffff | 64 KiB | Dev RW XN | BCM Peripheral Interrupt Controller
179+
[ 4.334273] -------------------------------------------------------------------------------------------------------------------------------------------
180+
179181
```
180182

181183
Raspberry Pi 4:
@@ -189,18 +191,20 @@ Precomputing kernel translation tables and patching kernel ELF
189191
Section Start Virt Addr Size
190192
--------------------------------------------------
191193
Generating Code and RO data | 0xffff_ffff_8008_0000 | 64 KiB
192-
Generating Data and bss | 0xffff_ffff_8009_0000 | 448 KiB
193-
Generating Boot-core stack | 0xffff_ffff_8011_0000 | 512 KiB
194+
Generating Data and bss | 0xffff_ffff_8009_0000 | 384 KiB
195+
Generating Boot-core stack | 0xffff_ffff_8010_0000 | 512 KiB
194196
--------------------------------------------------
195-
Patching Kernel table struct at physical 0xa_0000
196-
Patching Value of kernel table physical base address (0xe_0000) at physical 0x8_0068
197+
Patching Kernel table struct at physical 0x9_0000
198+
Patching Value of kernel table physical base address (0xd_0000) at physical 0x8_0080
197199
Finished in 0.03s
198200

201+
199202
Minipush 1.0
200203

201204
[MP] ⏳ Waiting for /dev/ttyUSB0
202205
[MP] ✅ Serial connected
203206
[MP] 🔌 Please power the target now
207+
204208
__ __ _ _ _ _
205209
| \/ (_)_ _ (_) | ___ __ _ __| |
206210
| |\/| | | ' \| | |__/ _ \/ _` / _` |
@@ -209,23 +213,24 @@ Minipush 1.0
209213
Raspberry Pi 4
210214

211215
[ML] Requesting binary
212-
[MP] ⏩ Pushing 449 KiB ======================================🦀 100% 112 KiB/s Time: 00:00:04
216+
[MP] ⏩ Pushing 394 KiB =======================================🦀 100% 98 KiB/s Time: 00:00:04
213217
[ML] Loaded! Executing the payload now
214218

215-
[ 5.009551] mingo version 0.16.0
216-
[ 5.009585] Booting on: Raspberry Pi 4
217-
[ 5.010040] MMU online:
218-
[ 5.010332] -------------------------------------------------------------------------------------------------------------------------------------------
219-
[ 5.012077] Virtual Physical Size Attr Entity
220-
[ 5.013821] -------------------------------------------------------------------------------------------------------------------------------------------
221-
[ 5.015566] 0xffff_ffff_8008_0000..0xffff_ffff_8008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
222-
[ 5.017181] 0xffff_ffff_8009_0000..0xffff_ffff_800f_ffff --> 0x00_0009_0000..0x00_000f_ffff | 448 KiB | C RW XN | Kernel data and bss
223-
[ 5.018751] 0xffff_ffff_8011_0000..0xffff_ffff_8018_ffff --> 0x00_0011_0000..0x00_0018_ffff | 512 KiB | C RW XN | Kernel boot-core stack
224-
[ 5.020354] 0xffff_ffff_f000_0000..0xffff_ffff_f000_ffff --> 0x00_fe20_0000..0x00_fe20_ffff | 64 KiB | Dev RW XN | BCM GPIO
225-
[ 5.021805] | BCM PL011 UART
226-
[ 5.023322] 0xffff_ffff_f001_0000..0xffff_ffff_f001_ffff --> 0x00_ff84_0000..0x00_ff84_ffff | 64 KiB | Dev RW XN | GICD
227-
[ 5.024730] | GICC
228-
[ 5.026138] -------------------------------------------------------------------------------------------------------------------------------------------
219+
[ 4.401227] mingo version 0.16.0
220+
[ 4.401260] Booting on: Raspberry Pi 4
221+
[ 4.401715] MMU online:
222+
[ 4.402008] -------------------------------------------------------------------------------------------------------------------------------------------
223+
[ 4.403752] Virtual Physical Size Attr Entity
224+
[ 4.405496] -------------------------------------------------------------------------------------------------------------------------------------------
225+
[ 4.407241] 0xffff_ffff_8008_0000..0xffff_ffff_8008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
226+
[ 4.408855] 0xffff_ffff_8009_0000..0xffff_ffff_800e_ffff --> 0x00_0009_0000..0x00_000e_ffff | 384 KiB | C RW XN | Kernel data and bss
227+
[ 4.410425] 0xffff_ffff_8010_0000..0xffff_ffff_8017_ffff --> 0x00_0010_0000..0x00_0017_ffff | 512 KiB | C RW XN | Kernel boot-core stack
228+
[ 4.412028] 0xffff_ffff_f000_0000..0xffff_ffff_f000_ffff --> 0x00_fe20_0000..0x00_fe20_ffff | 64 KiB | Dev RW XN | BCM GPIO
229+
[ 4.413480] | BCM PL011 UART
230+
[ 4.414997] 0xffff_ffff_f001_0000..0xffff_ffff_f001_ffff --> 0x00_ff84_0000..0x00_ff84_ffff | 64 KiB | Dev RW XN | GICD
231+
[ 4.416405] | GICC
232+
[ 4.417814] -------------------------------------------------------------------------------------------------------------------------------------------
233+
229234
```
230235

231236
## Diff to previous
@@ -361,7 +366,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
361366
/// Page descriptors, covering 64 KiB windows per entry.
362367
lvl3: [[PageDescriptor; 8192]; NUM_TABLES],
363368

364-
@@ -262,14 +262,23 @@
369+
@@ -305,14 +305,23 @@
365370
where
366371
[u8; Self::SIZE >> Granule512MiB::SHIFT]: Sized,
367372
{
@@ -387,7 +392,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
387392
/// Create an instance.
388393
#[allow(clippy::assertions_on_constants)]
389394
const fn _new(for_precompute: bool) -> Self {
390-
@@ -298,20 +307,32 @@
395+
@@ -341,20 +350,32 @@
391396
/// The start address of the table's MMIO range.
392397
#[inline(always)]
393398
fn mmio_start_addr(&self) -> Address<Virtual> {
@@ -424,12 +429,12 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
424429
}
425430

426431
/// Helper to calculate the lvl2 and lvl3 indices from an address.
427-
@@ -320,7 +341,12 @@
432+
@@ -363,7 +384,12 @@
428433
&self,
429-
addr: *const Page<Virtual>,
434+
virt_page: *const Page<Virtual>,
430435
) -> Result<(usize, usize), &'static str> {
431-
- let addr = addr as usize;
432-
+ let mut addr = addr as usize;
436+
- let addr = virt_page as usize;
437+
+ let mut addr = virt_page as usize;
433438
+
434439
+ if START_FROM_TOP {
435440
+ addr -= Self::START_FROM_TOP_OFFSET.into_usize()
@@ -438,7 +443,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
438443
let lvl2_index = addr >> Granule512MiB::SHIFT;
439444
let lvl3_index = (addr & Granule512MiB::MASK) >> Granule64KiB::SHIFT;
440445

441-
@@ -347,8 +373,9 @@
446+
@@ -411,8 +437,9 @@
442447
// OS Interface Code
443448
//------------------------------------------------------------------------------
444449

@@ -450,7 +455,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
450455
{
451456
fn init(&mut self) -> Result<(), &'static str> {
452457
if self.initialized {
453-
@@ -423,12 +450,16 @@
458+
@@ -483,12 +510,16 @@
454459
return Err("Not enough MMIO space left");
455460
}
456461

@@ -468,7 +473,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/_arch/aarch64/memory/mmu/t
468473
Ok(PageSliceDescriptor::from_addr(addr, num_pages))
469474
}
470475

471-
@@ -451,7 +482,7 @@
476+
@@ -549,7 +580,7 @@
472477
//--------------------------------------------------------------------------------------------------
473478

474479
#[cfg(test)]
@@ -571,7 +576,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/bsp/raspberrypi/link.ld 16
571576
diff -uNr 15_virtual_mem_part3_precomputed_tables/src/bsp/raspberrypi/memory/mmu.rs 16_virtual_mem_part4_higher_half_kernel/src/bsp/raspberrypi/memory/mmu.rs
572577
--- 15_virtual_mem_part3_precomputed_tables/src/bsp/raspberrypi/memory/mmu.rs
573578
+++ 16_virtual_mem_part4_higher_half_kernel/src/bsp/raspberrypi/memory/mmu.rs
574-
@@ -23,7 +23,7 @@
579+
@@ -22,7 +22,7 @@
575580
//--------------------------------------------------------------------------------------------------
576581

577582
type KernelTranslationTable =
@@ -600,7 +605,7 @@ diff -uNr 15_virtual_mem_part3_precomputed_tables/src/lib.rs 16_virtual_mem_part
600605
diff -uNr 15_virtual_mem_part3_precomputed_tables/src/memory/mmu.rs 16_virtual_mem_part4_higher_half_kernel/src/memory/mmu.rs
601606
--- 15_virtual_mem_part3_precomputed_tables/src/memory/mmu.rs
602607
+++ 16_virtual_mem_part4_higher_half_kernel/src/memory/mmu.rs
603-
@@ -80,6 +80,11 @@
608+
@@ -64,6 +64,11 @@
604609
pub trait AssociatedTranslationTable {
605610
/// A translation table whose address range is:
606611
///

‎16_virtual_mem_part4_higher_half_kernel/src/_arch/aarch64/memory/mmu.rs

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
use crate::{
1717
bsp, memory,
18-
memory::{mmu::TranslationGranule, Address, Physical, Virtual},
18+
memory::{mmu::TranslationGranule, Address, Physical},
1919
};
2020
use core::intrinsics::unlikely;
2121
use cortex_a::{asm::barrier, registers::*};
@@ -111,7 +111,7 @@ pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
111111
//------------------------------------------------------------------------------
112112
// OS Interface Code
113113
//------------------------------------------------------------------------------
114-
use memory::mmu::{MMUEnableError, TranslationError};
114+
use memory::mmu::MMUEnableError;
115115

116116
impl memory::mmu::interface::MMU for MemoryManagementUnit {
117117
unsafe fn enable_mmu_and_caching(
@@ -155,31 +155,4 @@ impl memory::mmu::interface::MMU for MemoryManagementUnit {
155155
fn is_enabled(&self) -> bool {
156156
SCTLR_EL1.matches_all(SCTLR_EL1::M::Enable)
157157
}
158-
159-
fn try_virt_to_phys(
160-
&self,
161-
virt: Address<Virtual>,
162-
) -> Result<Address<Physical>, TranslationError> {
163-
if !self.is_enabled() {
164-
return Err(TranslationError::MMUDisabled);
165-
}
166-
167-
let addr = virt.into_usize() as u64;
168-
unsafe {
169-
asm!(
170-
"AT S1E1R, {0}",
171-
in(reg) addr,
172-
options(readonly, nostack, preserves_flags)
173-
);
174-
}
175-
176-
let par_el1 = PAR_EL1.extract();
177-
if par_el1.matches_all(PAR_EL1::F::TranslationAborted) {
178-
return Err(TranslationError::Aborted);
179-
}
180-
181-
let phys_addr = (par_el1.read(PAR_EL1::PA) << 12) | (addr & 0xFFF);
182-
183-
Ok(Address::new(phys_addr as usize))
184-
}
185158
}

‎16_virtual_mem_part4_higher_half_kernel/src/_arch/aarch64/memory/mmu/translation_table.rs

Lines changed: 123 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
Address, Physical, Virtual,
2424
},
2525
};
26-
use core::convert::{self, TryInto};
26+
use core::convert;
2727
use tock_registers::{
2828
interfaces::{Readable, Writeable},
2929
register_bitfields,
@@ -219,6 +219,35 @@ impl convert::From<AttributeFields>
219219
}
220220
}
221221

222+
/// Convert the HW-specific attributes of the MMU to kernel's generic memory attributes.
223+
impl convert::TryFrom<InMemoryRegister<u64, STAGE1_PAGE_DESCRIPTOR::Register>> for AttributeFields {
224+
type Error = &'static str;
225+
226+
fn try_from(
227+
desc: InMemoryRegister<u64, STAGE1_PAGE_DESCRIPTOR::Register>,
228+
) -> Result<AttributeFields, Self::Error> {
229+
let mem_attributes = match desc.read(STAGE1_PAGE_DESCRIPTOR::AttrIndx) {
230+
memory::mmu::arch_mmu::mair::NORMAL => MemAttributes::CacheableDRAM,
231+
memory::mmu::arch_mmu::mair::DEVICE => MemAttributes::Device,
232+
_ => return Err("Unexpected memory attribute"),
233+
};
234+
235+
let acc_perms = match desc.read_as_enum(STAGE1_PAGE_DESCRIPTOR::AP) {
236+
Some(STAGE1_PAGE_DESCRIPTOR::AP::Value::RO_EL1) => AccessPermissions::ReadOnly,
237+
Some(STAGE1_PAGE_DESCRIPTOR::AP::Value::RW_EL1) => AccessPermissions::ReadWrite,
238+
_ => return Err("Unexpected access permission"),
239+
};
240+
241+
let execute_never = desc.read(STAGE1_PAGE_DESCRIPTOR::PXN) > 0;
242+
243+
Ok(AttributeFields {
244+
mem_attributes,
245+
acc_perms,
246+
execute_never,
247+
})
248+
}
249+
}
250+
222251
impl PageDescriptor {
223252
/// Create an instance.
224253
///
@@ -228,13 +257,13 @@ impl PageDescriptor {
228257
}
229258

230259
/// Create an instance.
231-
pub fn from_output_addr(
232-
phys_output_addr: *const Page<Physical>,
260+
pub fn from_output_page(
261+
phys_output_page: *const Page<Physical>,
233262
attribute_fields: &AttributeFields,
234263
) -> Self {
235264
let val = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(0);
236265

237-
let shifted = phys_output_addr as u64 >> Granule64KiB::SHIFT;
266+
let shifted = phys_output_page as u64 >> Granule64KiB::SHIFT;
238267
val.write(
239268
STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB.val(shifted)
240269
+ STAGE1_PAGE_DESCRIPTOR::AF::True
@@ -251,6 +280,20 @@ impl PageDescriptor {
251280
InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value)
252281
.is_set(STAGE1_PAGE_DESCRIPTOR::VALID)
253282
}
283+
284+
/// Returns the output page.
285+
fn output_page(&self) -> *const Page<Physical> {
286+
let shifted = InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value)
287+
.read(STAGE1_PAGE_DESCRIPTOR::OUTPUT_ADDR_64KiB);
288+
let addr = shifted << Granule64KiB::SHIFT;
289+
290+
addr as *const Page<Physical>
291+
}
292+
293+
/// Returns the attributes.
294+
fn try_attributes(&self) -> Result<AttributeFields, &'static str> {
295+
InMemoryRegister::<u64, STAGE1_PAGE_DESCRIPTOR::Register>::new(self.value).try_into()
296+
}
254297
}
255298

256299
//--------------------------------------------------------------------------------------------------
@@ -337,11 +380,11 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
337380

338381
/// Helper to calculate the lvl2 and lvl3 indices from an address.
339382
#[inline(always)]
340-
fn lvl2_lvl3_index_from(
383+
fn lvl2_lvl3_index_from_page(
341384
&self,
342-
addr: *const Page<Virtual>,
385+
virt_page: *const Page<Virtual>,
343386
) -> Result<(usize, usize), &'static str> {
344-
let mut addr = addr as usize;
387+
let mut addr = virt_page as usize;
345388

346389
if START_FROM_TOP {
347390
addr -= Self::START_FROM_TOP_OFFSET.into_usize()
@@ -357,15 +400,36 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
357400
Ok((lvl2_index, lvl3_index))
358401
}
359402

360-
/// Returns the PageDescriptor corresponding to the supplied Page.
403+
/// Returns the PageDescriptor corresponding to the supplied page address.
361404
#[inline(always)]
362-
fn page_descriptor_from(
405+
fn page_descriptor_from_page(
406+
&self,
407+
virt_page: *const Page<Virtual>,
408+
) -> Result<&PageDescriptor, &'static str> {
409+
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
410+
let desc = &self.lvl3[lvl2_index][lvl3_index];
411+
412+
Ok(desc)
413+
}
414+
415+
/// Sets the PageDescriptor corresponding to the supplied page address.
416+
///
417+
/// Doesn't allow overriding an already valid page.
418+
#[inline(always)]
419+
fn set_page_descriptor_from_page(
363420
&mut self,
364-
addr: *const Page<Virtual>,
365-
) -> Result<&mut PageDescriptor, &'static str> {
366-
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from(addr)?;
421+
virt_page: *const Page<Virtual>,
422+
new_desc: &PageDescriptor,
423+
) -> Result<(), &'static str> {
424+
let (lvl2_index, lvl3_index) = self.lvl2_lvl3_index_from_page(virt_page)?;
425+
let desc = &mut self.lvl3[lvl2_index][lvl3_index];
426+
427+
if desc.is_valid() {
428+
return Err("Virtual page is already mapped");
429+
}
367430

368-
Ok(&mut self.lvl3[lvl2_index][lvl3_index])
431+
*desc = *new_desc;
432+
Ok(())
369433
}
370434
}
371435

@@ -384,13 +448,11 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
384448

385449
// Populate the l2 entries.
386450
for (lvl2_nr, lvl2_entry) in self.lvl2.iter_mut().enumerate() {
387-
let addr = self.lvl3[lvl2_nr]
388-
.virt_start_addr()
389-
.try_into()
390-
.map_err(|_| "Translation error")?;
451+
let virt_table_addr = self.lvl3[lvl2_nr].virt_start_addr();
452+
let phys_table_addr = memory::mmu::try_kernel_virt_addr_to_phys_addr(virt_table_addr)?;
391453

392-
let desc = TableDescriptor::from_next_lvl_table_addr(addr);
393-
*lvl2_entry = desc;
454+
let new_desc = TableDescriptor::from_next_lvl_table_addr(phys_table_addr);
455+
*lvl2_entry = new_desc;
394456
}
395457

396458
self.cur_l3_mmio_index = Self::L3_MMIO_START_INDEX;
@@ -407,8 +469,8 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
407469
) -> Result<(), &'static str> {
408470
assert!(self.initialized, "Translation tables not initialized");
409471

410-
let p = phys_pages.as_slice();
411472
let v = virt_pages.as_slice();
473+
let p = phys_pages.as_slice();
412474

413475
// No work to do for empty slices.
414476
if v.is_empty() {
@@ -425,12 +487,10 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
425487

426488
let iter = p.iter().zip(v.iter());
427489
for (phys_page, virt_page) in iter {
428-
let page_descriptor = self.page_descriptor_from(virt_page.as_ptr())?;
429-
if page_descriptor.is_valid() {
430-
return Err("Virtual page is already mapped");
431-
}
490+
let new_desc = PageDescriptor::from_output_page(phys_page.as_ptr(), attr);
491+
let virt_page = virt_page.as_ptr();
432492

433-
*page_descriptor = PageDescriptor::from_output_addr(phys_page.as_ptr(), attr);
493+
self.set_page_descriptor_from_page(virt_page, &new_desc)?;
434494
}
435495

436496
Ok(())
@@ -475,6 +535,44 @@ impl<const NUM_TABLES: usize, const START_FROM_TOP: bool>
475535

476536
false
477537
}
538+
539+
fn try_virt_page_to_phys_page(
540+
&self,
541+
virt_page: *const Page<Virtual>,
542+
) -> Result<*const Page<Physical>, &'static str> {
543+
let page_desc = self.page_descriptor_from_page(virt_page)?;
544+
545+
if !page_desc.is_valid() {
546+
return Err("Page marked invalid");
547+
}
548+
549+
Ok(page_desc.output_page())
550+
}
551+
552+
fn try_page_attributes(
553+
&self,
554+
virt_page: *const Page<Virtual>,
555+
) -> Result<AttributeFields, &'static str> {
556+
let page_desc = self.page_descriptor_from_page(virt_page)?;
557+
558+
if !page_desc.is_valid() {
559+
return Err("Page marked invalid");
560+
}
561+
562+
page_desc.try_attributes()
563+
}
564+
565+
/// Try to translate a virtual address to a physical address.
566+
///
567+
/// Will only succeed if there exists a valid mapping for the input address.
568+
fn try_virt_addr_to_phys_addr(
569+
&self,
570+
virt_addr: Address<Virtual>,
571+
) -> Result<Address<Physical>, &'static str> {
572+
let page = self.try_virt_page_to_phys_page(virt_addr.as_page_ptr())?;
573+
574+
Ok(Address::new(page as usize + virt_addr.offset_into_page()))
575+
}
478576
}
479577

480578
//--------------------------------------------------------------------------------------------------

‎16_virtual_mem_part4_higher_half_kernel/src/bsp/raspberrypi/memory/mmu.rs

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ use crate::{
99
memory::{
1010
mmu as generic_mmu,
1111
mmu::{
12-
AccessPermissions, AddressSpace, AssociatedTranslationTable, AttributeFields,
13-
MemAttributes, Page, PageSliceDescriptor, TranslationGranule,
12+
AddressSpace, AssociatedTranslationTable, AttributeFields, Page, PageSliceDescriptor,
13+
TranslationGranule,
1414
},
15-
Physical, Virtual,
15+
Address, Physical, Virtual,
1616
},
1717
synchronization::InitStateLock,
1818
};
19-
use core::convert::TryInto;
2019

2120
//--------------------------------------------------------------------------------------------------
2221
// Private Definitions
@@ -103,21 +102,19 @@ fn virt_boot_core_stack_page_desc() -> PageSliceDescriptor<Virtual> {
103102
}
104103

105104
// There is no reason to expect the following conversions to fail, since they were generated offline
106-
// by the `translation table tool`. If it doesn't work, a panic due to the unwrap is justified.
107-
108-
/// The Read+Execute (RX) pages of the kernel binary.
109-
fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
110-
virt_rx_page_desc().try_into().unwrap()
111-
}
112-
113-
/// The Read+Write (RW) pages of the kernel binary.
114-
fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
115-
virt_rw_page_desc().try_into().unwrap()
105+
// by the `translation table tool`. If it doesn't work, a panic due to the unwraps is justified.
106+
fn kernel_virt_to_phys_page_slice(
107+
virt_slice: PageSliceDescriptor<Virtual>,
108+
) -> PageSliceDescriptor<Physical> {
109+
let phys_first_page =
110+
generic_mmu::try_kernel_virt_page_to_phys_page(virt_slice.first_page()).unwrap();
111+
let phys_start_addr = Address::new(phys_first_page as usize);
112+
113+
PageSliceDescriptor::from_addr(phys_start_addr, virt_slice.num_pages())
116114
}
117115

118-
/// The boot core's stack.
119-
fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
120-
virt_boot_core_stack_page_desc().try_into().unwrap()
116+
fn kernel_page_attributes(virt_page: *const Page<Virtual>) -> AttributeFields {
117+
generic_mmu::try_kernel_page_attributes(virt_page).unwrap()
121118
}
122119

123120
//--------------------------------------------------------------------------------------------------
@@ -142,39 +139,28 @@ pub fn phys_addr_space_end_page() -> *const Page<Physical> {
142139
/// The actual translation table entries for the kernel binary are generated using the offline
143140
/// `translation table tool` and patched into the kernel binary. This function just adds the mapping
144141
/// record entries.
145-
///
146-
/// It must be ensured that these entries are in sync with the offline tool.
147142
pub fn kernel_add_mapping_records_for_precomputed() {
143+
let virt_rx_page_desc = virt_rx_page_desc();
148144
generic_mmu::kernel_add_mapping_record(
149145
"Kernel code and RO data",
150-
&virt_rx_page_desc(),
151-
&phys_rx_page_desc(),
152-
&AttributeFields {
153-
mem_attributes: MemAttributes::CacheableDRAM,
154-
acc_perms: AccessPermissions::ReadOnly,
155-
execute_never: false,
156-
},
146+
&virt_rx_page_desc,
147+
&kernel_virt_to_phys_page_slice(virt_rx_page_desc),
148+
&kernel_page_attributes(virt_rx_page_desc.first_page()),
157149
);
158150

151+
let virt_rw_page_desc = virt_rw_page_desc();
159152
generic_mmu::kernel_add_mapping_record(
160153
"Kernel data and bss",
161-
&virt_rw_page_desc(),
162-
&phys_rw_page_desc(),
163-
&AttributeFields {
164-
mem_attributes: MemAttributes::CacheableDRAM,
165-
acc_perms: AccessPermissions::ReadWrite,
166-
execute_never: true,
167-
},
154+
&virt_rw_page_desc,
155+
&kernel_virt_to_phys_page_slice(virt_rw_page_desc),
156+
&kernel_page_attributes(virt_rw_page_desc.first_page()),
168157
);
169158

159+
let virt_boot_core_stack_page_desc = virt_boot_core_stack_page_desc();
170160
generic_mmu::kernel_add_mapping_record(
171161
"Kernel boot-core stack",
172-
&virt_boot_core_stack_page_desc(),
173-
&phys_boot_core_stack_page_desc(),
174-
&AttributeFields {
175-
mem_attributes: MemAttributes::CacheableDRAM,
176-
acc_perms: AccessPermissions::ReadWrite,
177-
execute_never: true,
178-
},
162+
&virt_boot_core_stack_page_desc,
163+
&kernel_virt_to_phys_page_slice(virt_boot_core_stack_page_desc),
164+
&kernel_page_attributes(virt_boot_core_stack_page_desc.first_page()),
179165
);
180166
}

‎16_virtual_mem_part4_higher_half_kernel/src/memory.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
77
pub mod mmu;
88

9-
use crate::common;
9+
use crate::{bsp, common};
1010
use core::{
11-
convert::TryFrom,
1211
fmt,
1312
marker::PhantomData,
1413
ops::{AddAssign, SubAssign},
1514
};
15+
use mmu::Page;
1616

1717
//--------------------------------------------------------------------------------------------------
1818
// Public Definitions
@@ -66,13 +66,16 @@ impl<ATYPE: AddressType> Address<ATYPE> {
6666
pub const fn into_usize(self) -> usize {
6767
self.value
6868
}
69-
}
7069

71-
impl TryFrom<Address<Virtual>> for Address<Physical> {
72-
type Error = mmu::TranslationError;
70+
/// Return a pointer to the page that contains this address.
71+
pub const fn as_page_ptr(&self) -> *const Page<ATYPE> {
72+
self.align_down(bsp::memory::mmu::KernelGranule::SIZE)
73+
.into_usize() as *const _
74+
}
7375

74-
fn try_from(virt: Address<Virtual>) -> Result<Self, Self::Error> {
75-
mmu::try_virt_to_phys(virt)
76+
/// Return the address' offset into the underlying page.
77+
pub const fn offset_into_page(&self) -> usize {
78+
self.value & bsp::memory::mmu::KernelGranule::MASK
7679
}
7780
}
7881

‎16_virtual_mem_part4_higher_half_kernel/src/memory/mmu.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,6 @@ pub enum MMUEnableError {
3333
Other(&'static str),
3434
}
3535

36-
/// Translation error variants.
37-
#[allow(missing_docs)]
38-
#[derive(Debug)]
39-
pub enum TranslationError {
40-
MMUDisabled,
41-
Aborted,
42-
}
43-
4436
/// Memory Management interfaces.
4537
pub mod interface {
4638
use super::*;
@@ -59,14 +51,6 @@ pub mod interface {
5951

6052
/// Returns true if the MMU is enabled, false otherwise.
6153
fn is_enabled(&self) -> bool;
62-
63-
/// Try to translate a virtual address to a physical address.
64-
///
65-
/// Will only succeed if there exists a valid mapping for the input VA.
66-
fn try_virt_to_phys(
67-
&self,
68-
virt: Address<Virtual>,
69-
) -> Result<Address<Physical>, TranslationError>;
7054
}
7155
}
7256

@@ -245,11 +229,34 @@ pub unsafe fn kernel_map_mmio(
245229
Ok(virt_addr + offset_into_start_page)
246230
}
247231

248-
/// Try to translate a virtual address to a physical address.
232+
/// Try to translate a kernel virtual page pointer to a physical page pointer.
233+
///
234+
/// Will only succeed if there exists a valid mapping for the input page.
235+
pub fn try_kernel_virt_page_to_phys_page(
236+
virt_page: *const Page<Virtual>,
237+
) -> Result<*const Page<Physical>, &'static str> {
238+
bsp::memory::mmu::kernel_translation_tables()
239+
.read(|tables| tables.try_virt_page_to_phys_page(virt_page))
240+
}
241+
242+
/// Try to get the attributes of a kernel page.
243+
///
244+
/// Will only succeed if there exists a valid mapping for the input page.
245+
pub fn try_kernel_page_attributes(
246+
virt_page: *const Page<Virtual>,
247+
) -> Result<AttributeFields, &'static str> {
248+
bsp::memory::mmu::kernel_translation_tables()
249+
.read(|tables| tables.try_page_attributes(virt_page))
250+
}
251+
252+
/// Try to translate a kernel virtual address to a physical address.
249253
///
250-
/// Will only succeed if there exists a valid mapping for the input VA.
251-
pub fn try_virt_to_phys(virt: Address<Virtual>) -> Result<Address<Physical>, TranslationError> {
252-
arch_mmu::mmu().try_virt_to_phys(virt)
254+
/// Will only succeed if there exists a valid mapping for the input address.
255+
fn try_kernel_virt_addr_to_phys_addr(
256+
virt_addr: Address<Virtual>,
257+
) -> Result<Address<Physical>, &'static str> {
258+
bsp::memory::mmu::kernel_translation_tables()
259+
.read(|tables| tables.try_virt_addr_to_phys_addr(virt_addr))
253260
}
254261

255262
/// Enable the MMU and data + instruction caching.

‎16_virtual_mem_part4_higher_half_kernel/src/memory/mmu/translation_table.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod arch_translation_table;
1010

1111
use crate::memory::{
1212
mmu::{AttributeFields, PageSliceDescriptor},
13-
Physical, Virtual,
13+
Address, Page, Physical, Virtual,
1414
};
1515

1616
//--------------------------------------------------------------------------------------------------
@@ -67,6 +67,30 @@ pub mod interface {
6767

6868
/// Check if a virtual page splice is in the "MMIO region".
6969
fn is_virt_page_slice_mmio(&self, virt_pages: &PageSliceDescriptor<Virtual>) -> bool;
70+
71+
/// Try to translate a virtual page pointer to a physical page pointer.
72+
///
73+
/// Will only succeed if there exists a valid mapping for the input page.
74+
fn try_virt_page_to_phys_page(
75+
&self,
76+
virt_page: *const Page<Virtual>,
77+
) -> Result<*const Page<Physical>, &'static str>;
78+
79+
/// Try to get the attributes of a page.
80+
///
81+
/// Will only succeed if there exists a valid mapping for the input page.
82+
fn try_page_attributes(
83+
&self,
84+
virt_page: *const Page<Virtual>,
85+
) -> Result<AttributeFields, &'static str>;
86+
87+
/// Try to translate a virtual address to a physical address.
88+
///
89+
/// Will only succeed if there exists a valid mapping for the input address.
90+
fn try_virt_addr_to_phys_addr(
91+
&self,
92+
virt_addr: Address<Virtual>,
93+
) -> Result<Address<Physical>, &'static str>;
7094
}
7195
}
7296

‎16_virtual_mem_part4_higher_half_kernel/src/memory/mmu/types.rs

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
77
use crate::{
88
bsp, common,
9-
memory::{Address, AddressType, Physical, Virtual},
10-
};
11-
use core::{
12-
convert::{From, TryFrom},
13-
marker::PhantomData,
9+
memory::{Address, AddressType, Physical},
1410
};
11+
use core::{convert::From, marker::PhantomData};
1512

1613
//--------------------------------------------------------------------------------------------------
1714
// Public Definitions
@@ -95,11 +92,11 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
9592
}
9693

9794
/// Return a pointer to the first page of the described slice.
98-
const fn first_page_ptr(&self) -> *const Page<ATYPE> {
95+
pub const fn first_page(&self) -> *const Page<ATYPE> {
9996
self.start.into_usize() as *const _
10097
}
10198

102-
/// Return the number of Pages the slice describes.
99+
/// Return the number of pages the slice describes.
103100
pub const fn num_pages(&self) -> usize {
104101
self.num_pages
105102
}
@@ -129,26 +126,13 @@ impl<ATYPE: AddressType> PageSliceDescriptor<ATYPE> {
129126
(addr >= self.start_addr()) && (addr <= self.end_addr_inclusive())
130127
}
131128

132-
/// Return a non-mutable slice of Pages.
129+
/// Return a non-mutable slice of pages.
133130
///
134131
/// # Safety
135132
///
136133
/// - Same as applies for `core::slice::from_raw_parts`.
137134
pub unsafe fn as_slice(&self) -> &[Page<ATYPE>] {
138-
core::slice::from_raw_parts(self.first_page_ptr(), self.num_pages)
139-
}
140-
}
141-
142-
impl TryFrom<PageSliceDescriptor<Virtual>> for PageSliceDescriptor<Physical> {
143-
type Error = super::TranslationError;
144-
145-
fn try_from(desc: PageSliceDescriptor<Virtual>) -> Result<Self, Self::Error> {
146-
let phys_start = super::try_virt_to_phys(desc.start)?;
147-
148-
Ok(Self {
149-
start: phys_start,
150-
num_pages: desc.num_pages,
151-
})
135+
core::slice::from_raw_parts(self.first_page(), self.num_pages)
152136
}
153137
}
154138

0 commit comments

Comments
 (0)
Please sign in to comment.